0
点赞
收藏
分享

微信扫一扫

基于Django框架的网络云盘设计

weednoah 2022-03-16 阅读 73

基于Django框架的网络云盘设计

网络云盘设计流程(第一篇)

前言

这是一款基于Python语言,Django框架的网络云盘,内容较多,我将整个项目分为三篇文章来讲解,这是第一篇,主要讲述内容包括环境的搭建,Django各文件的配置情况,以及呈现一个简单的云盘网站(功能未完善,剩余部分将在第二篇讲述),谢谢大家的持续关注!

前期准备与环境搭建

作为网站的必备,你需要一台云主机,建议选择Windows镜像,拿到云主机之后你需要配置Pycharm专业版软件(这里必须是专业版,社区版没有Django服务),以及Python环境。
在这里插入图片描述
环境配置好后你需要添加入站和出站规则,端口号就写你希望外界访问的端口号。(图片略)
最后你需要配置数据库,SQL server,Mysql都可以,我这里使用的是SQL server。数据库安装后记得开启TCP服务。在这里插入图片描述
以上就是全部的环境搭建,服务器配置不错的小伙伴们可以安装Anaconda和SQL server Manager,以便于扩展更多功能。以上过程如果遇到问题请大家自行百度哈~

创建一个Django工程,跑一个HelloWorld

点击New Project,选择Django,选择自己本机的Python环境,点击create。点击右上角Edit Configurations,将Host改为0.0.0.0,端口号自己定义。
在这里插入图片描述
打开你工程目录下的urls.py文件,代码改为

from django.contrib import admin
from django.urls import path, re_path
urlpatterns = [
    path('hello', Do.hello, name='hello'),
]

这里大致意思为,访问XXX.XXX.XXX.XXX:XXX/hello这个url时,会调用DO.py文件中的hello函数。
接下来在工程主目录下新建Do.py文件(也可以是其他名字,但要在urls.py文件上做相应修改)

import json
import time
from urllib import parse
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
import pymssql
from django.contrib import messages
from django.shortcuts import render
from Biye.settings import BASE_DIR
def hello(request):
    return render(request, './hello.html')

接下来修改settings.py文件

ROOT_URLCONF = 'Biye.urls'#这里是指定项目的url配置文件
STATIC_URL = '/static/'#这里是设置存放网页CSS的目录
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static/'),
)
ALLOWED_HOSTS = ['*']#这里是设置开放端口
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR , 'templates'],#这里是指定html文件位置
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

接下来在templates文件夹下新建hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a>hello world</a>
</body>
</html>

运行工程,使用另一台电脑或者手机访问XXX.XXX.XXX.XXX:XXX/hello,结果如下
在这里插入图片描述
以上就是新建一个Django工程的全部流程,下面云盘的设计也是基于这个基础之上的,希望小伙伴们自己动手尝试一下哦。

网盘设计简介及成果展示

设计这款云盘的初衷在于,更加便捷地在不同操作系统,不同设备之间传递文件,同时也是为了在毕设中存放训练模型和数据集。如果你是硬件大佬,经常需要在树莓派或者其他实时OS的开发板做项目,如果你经常需要在WIndows系统和Linux系统之间传递文件,并且曾被文件系统的差异造成困扰,那么这款网络云盘一定适合你!
下面是网盘的几张图
在这里插入图片描述
在这里插入图片描述
云盘应具备以下几种功能
1.登录功能
2.注册功能(第二篇文章介绍)
3.存储空间内所有文件的展示,包括文件夹和其他文件
4.文件的备注,上传时间,文件大小展示,如遇到文件夹,应返回其所有子文件的大小之和
5.下载文件,批量下载文件
6.上传文件,批量上传文件
7.删除文件
8.上传文件进度条
9.下载整个文件夹(第二篇文章介绍)
10.搜索文件(第二篇文章介绍)
下面开始逐一介绍各功能的实现方式。

功能1,“登录”的实现

def index(request):
    if request.method == "POST":
        if request.POST.get("text1", None) != "" and request.POST.get("password", None) != "":
            connect = pymssql.connect('XXX', 'sa', 'XXX', 'XXX', charset='UTF-8')  # 服务器名,账户,密码,数据库名
            t1 = request.POST.get("text1", None)
            t2 = request.POST.get("password", None)
            cursor = connect.cursor()  # 创建一个游标对象,python里的sql语句都要通过cursor来执行
            sql = "select * from Denglu "
            cursor.execute(sql)  # 执行sql语句
            row = cursor.fetchone()  # 读取查询结果,
            aa = 0
            while row:  # 循环读取所有结果
                if t1 == row[0].strip() and t2 == row[1].strip():
                    aa = 1
                    cursor.close()  # 关闭游标
                    connect.close()  # 关闭连接
                    return render(request, './index.html')
                row = cursor.fetchone()
            if aa == 0:
                messages.success(request, "密码或用户名错误")
                cursor.close()  # 关闭游标
                connect.close()  # 关闭连接
                return render(request, '../templates/web.html')
    return render(request, '../templates/web.html')
{% load staticfiles %}
<html lang="zxx">

<!-- Head -->
<head>

    <title>家居控制终端</title>

    <!-- Meta-Tags -->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <!-- style CSS -->
    <link rel="stylesheet" href="/static/css/style.css" type="text/css" media="all">

    <!-- fontawesome -->
    <link rel="stylesheet" href="/static/css/font-awesome.min.css" type="text/css" media="all">

    <!-- google fonts -->
    <link href="//fonts.googleapis.com/css?family=Mukta:300,400,500" rel="stylesheet">

</head>
<!-- //Head -->

<!-- Body -->
<body>

    <section class="main">

        <div class="bottom-grid">
            <div class="logo">
                <h1> <a href="index.html"> 欢迎登录</a></h1>
            </div>
        </div>
        <div class="content-w3ls">
            <div class="text-center icon">
                <span class="fa fa-meetup"></span>
            </div>

            <div class="content-bottom">
                <form action="./" method="post">
                    {% csrf_token %}
                    <div class="field-group">
                        <span class="fa fa-user" aria-hidden="true"></span>
                        <div class="wthree-field">
                            <input name="text1" id="text1" type="text" value="" placeholder="请输入用户名" required>
                        </div>
                    </div>
                    <div class="field-group">
                        <span class="fa fa-lock" aria-hidden="true"></span>
                        <div class="wthree-field">
                            <input name="password" id="myInput" type="Password" placeholder="请输入密码">
                        </div>
                    </div>
                    <div class="wthree-field">
                        <button type="submit" class="btn">登录</button>
                    </div>
                    <ul class="list-login">
                        <li class="switch-agileits">
                            <label class="switch">
                                <input type="checkbox">
                                <span class="slider round"></span>
                                保持登录状态
                            </label>
                        </li>
                        <li>
                            <a href="#" class="text-right">注册</a>
                        </li>
                        <li class="clearfix"></li>
                    </ul>
                    <ul class="list-login-bottom">

                        <li class="clearfix"></li>
                    </ul>
                </form>
            </div>
        </div>
        <div class="copyright">
            <p>© 2022 智能家居控制终端. All rights reserved | </a> </p>
        </div>
    </section>

</body>
<!-- //Body -->

</html>

这里的HTML来自网上的模板,大家想要自己的界面变得好看,都可以去网上找开源模板,主要写的是后端逻辑。
这段代码的主要逻辑是,submit按钮提交了一个form表单给后台,方法是POST,后台读取到文本框的输入内容,将字符串做处理后与数据库内容进行比对,如果与数据库某一条匹配则进入主系统,如果都不匹配返回登录失败。

功能3,4,“存储空间内所有文件的展示及文件描述”的实现

def yun(request):
    if request.method == "POST":
        obj = request.FILES.getlist('new11')
        for f in obj:
            destination = open(os.path.join(BASE_DIR, 'WebDict', f.name), 'wb')
            for chunk in f.chunks():
                destination.write(chunk)
            destination.close()
        # f = open(os.path.join(BASE_DIR, 'WebDict', obj.name), 'wb')
        # for chunk in obj.chunks():
        #     f.write(chunk)
        # f.close()
    file_dir = "WebDict"
    m = 0
    selectFiles = [] #记录文件名
    sizeFiles = []   #记录文件大小
    timeFiles = []   #记录文件创建时间
    FilesBig = []    #记录文件夹大小
    FileType = []    #记录文件描述
    FilePath = []    #记录文件路径
    for files in os.listdir(file_dir):
        m = m + 1
        print(files)
        selectFiles = selectFiles +[files]
        FilePath = FilePath + [file_dir + "/" + files]
        if os.path.isdir(file_dir + "/" + files):
            FileType = FileType +["文件夹"]

            full_size = sum(sum(os.path.getsize(os.path.join(parent, file)) for file in files) for parent, dirs, files in
                os.walk(file_dir + "/" + files))
            if full_size / float(1024) > 1024 :
                sizeFiles = sizeFiles + [round(full_size/ float(1024*1024), 1)]
                FilesBig = FilesBig + ["MB"]
            else:
                sizeFiles = sizeFiles + [round(full_size/ float(1024), 1)]
                FilesBig = FilesBig + ["KB"]
        else:
            FileType = FileType + [""]
            if os.path.getsize(file_dir + "/" + files) / float(1024)>1024:
                sizeFiles = sizeFiles + [round(os.path.getsize(file_dir + "/" + files) / float(1024*1024), 1)]
                FilesBig = FilesBig + ["MB"]
            else:
                sizeFiles = sizeFiles + [round(os.path.getsize(file_dir + "/" + files) / float(1024), 1)]
                FilesBig = FilesBig + ["KB"]
        timeFiles = timeFiles + [time.ctime(os.path.getctime(file_dir + "/" + files))]


    files = zip(selectFiles, sizeFiles, timeFiles,FilesBig,FileType,FilePath)
    return render(request, "yun.html", {"files": files})
 <table class="table table-striped table-bordered table-hover dataTable no-footer" id="dataTables-example" aria-describedby="dataTables-example_info">
                                    <thead>
                                        <tr role="row"><th class="sorting_asc" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" aria-label="Rendering engine: activate to sort column ascending" aria-sort="ascending" style="width: 153px;">文件名</th><th class="sorting" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" aria-label="Browser: activate to sort column ascending" style="width: 237px;">文件备注</th><th class="sorting" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" aria-label="Platform(s): activate to sort column ascending" style="width: 214px;">上传时间</th><th class="sorting" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" aria-label="Engine version: activate to sort column ascending" style="width: 128px;">文件大小</th><th class="sorting" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" aria-label="CSS grade: activate to sort column ascending" style="width: 89px;">删除文件</th></tr>
                                    </thead>
                                    <tbody>
                                    {% for xx,yy,zz,QQ,PP,NN in files %}
                                    <tr class="gradeA odd">

                                            <td class="sorting_1" width="30%">

                                                <input type="checkbox" name ={{ NN }} >
                                                {% if PP == "文件夹"%}
                                                <i class="fa fa-envelope fa-fw"></i>
                                                {% endif %}
                                                <a href="/download/{{ NN }}">{{ xx }}</a>
                                            </td>
                                            <td class=" ">{{ PP }}</td>
                                            <td class=" ">{{ zz }}</td>
                                            <td class="center ">{{ yy }} {{ QQ }}</td>
                                            <td class="center ">
                                                 <a href="/delete/WebDict/{{ xx }}">删除</a>
                                            </td>


                                        </tr>
                                    {% endfor %}
                                    </tbody>

这里yun函数的主要逻辑是,使用os.listdir函数读取存储空间内的所有文件,遍历所有文件,判断是否为文件夹,如果是文件夹则使用一个新url,返回文件夹里面的内容,如果是文件,则直接返回文件的url,供给下载。
在这里插入图片描述

功能5,“文件下载”的实现

def file_download(request, file_path):
    if os.path.isdir(file_path):
        m = 0
        selectFiles = []
        sizeFiles = []
        timeFiles = []
        FilesBig = []
        FileType = []
        FilePath = []

        for files in os.listdir(file_path):
            m = m + 1
            print(files)
            selectFiles = selectFiles + [files]
            FilePath = FilePath + [file_path + "/" + files]
            if os.path.isdir(file_path + "/" + files):
                FileType = FileType + ["文件夹"]
                full_size = sum(
                    sum(os.path.getsize(os.path.join(parent, file)) for file in files) for parent, dirs, files in
                    os.walk(file_path+ "/" + files))
                if full_size / float(1024) > 1024:
                    sizeFiles = sizeFiles + [round(full_size / float(1024 * 1024), 1)]
                    FilesBig = FilesBig + ["MB"]
                else:
                    sizeFiles = sizeFiles + [round(full_size / float(1024), 1)]
                    FilesBig = FilesBig + ["KB"]
            else:
                FileType = FileType + [""]
                if os.path.getsize(file_path + "/" + files) / float(1024) > 1024:
                    sizeFiles = sizeFiles + [round(os.path.getsize(file_path + "/" + files) / float(1024 * 1024), 1)]
                    FilesBig = FilesBig + ["MB"]
                else:
                    sizeFiles = sizeFiles + [round(os.path.getsize(file_path + "/" + files) / float(1024), 1)]
                    FilesBig = FilesBig + ["KB"]
            timeFiles = timeFiles + [time.ctime(os.path.getctime(file_path + "/" + files))]

        files = zip(selectFiles, sizeFiles, timeFiles, FilesBig, FileType, FilePath)
        return render(request, "yun.html", {"files": files})
    else:
        try:
            print(file_path)
            response = StreamingHttpResponse(open(file_path, 'rb'))
            response['content_type'] = "application/octet-stream"
            response['Content-Disposition'] = 'attachment; filename=' + parse.quote(file_path, encoding="utf-8")
            return response
        except Exception:
            raise Http404

这里的前半部分与文件展示代码类似,主要逻辑是判断文件类型,如果是文件夹则重新刷新表格,展示文件夹内的内容,如果是文件则返回一个文件流。

功能5,“批量文件下载”的实现

这里主要体现批量二字,需要为每一个文件在html中分配一个以文件名命名的checkbox控件。

{% for xx,yy,zz,QQ,PP,NN in files %}
<input type="checkbox" name ={{ NN }} >
  {% if PP == "文件夹"%}
<i class="fa fa-envelope fa-fw"></i>
  {% endif %}
  {% endfor %}

接下来需要编写Javascript代码

function multdownload(){
            var oTxt = document.getElementsByTagName("input");
            for (var i = 0; i < oTxt.length; i++) {
                if(oTxt[i].checked){
                    //alert(oTxt[i].name);
                    let a = document.createElement('a'); // 创建a标签
                    let e = document.createEvent('MouseEvents'); // 创建鼠标事件对象
                    e.initEvent('click', false, false); // 初始化事件对象
                    a.href = '/download/'+ oTxt[i].name; // 设置下载地址
                    a.download = oTxt[i].name; // 设置下载文件名
                    a.dispatchEvent(e);
                    oTxt[i].checked= false
                }
            }
}

这里逻辑比较简单,一个for循环即可实现
Django后台代码同上

功能6,“批量上传文件”的实现

同样,这里着重体现的是批量二字,这里html需要使用一个特殊的控件<p><input type="file" id="file" name="new11" multiple size="80"></p>加入了multiple属性,可以支持多选文件。
JavaScript代码

function UpladFile() {
var fileObj = document.getElementById("file").files[0]; // js 获取文件对象
var url = "XXXXX"; // 接收上传文件的后台地址
var form = new FormData(); // FormData 对象
form.append("mf", fileObj); // 文件对象
xhr = new XMLHttpRequest(); // XMLHttpRequest 对象
xhr.open("post", url, true);
xhr.onload = uploadComplete; 
xhr.onerror = uploadFailed; 
xhr.upload.onprogress = progressFunction;
xhr.upload.onloadstart = function(){//上传开始执行方法
ot = new Date().getTime(); //设置上传开始时间
oloaded = 0;//设置上传开始时,以上传的文件大小为0
};
xhr.send(form); //开始上传,发送form数据
}

功能7,“删除文件”的实现

这个功能比较简单就不介绍了,这里主要用到了os.remove(file_path)语句,其余同上。

功能8,“上传文件进度条”的实现

后台代码同“上传文件”,JavaScript代码如下

function progressFunction(evt) {
var progressBar = document.getElementById("progressBar");
var percentageDiv = document.getElementById("percentage");
if (evt.lengthComputable) {//
progressBar.max = evt.total;
progressBar.value = evt.loaded;
percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
}
var time = document.getElementById("time");
var nt = new Date().getTime();
var pertime = (nt-ot)/1000; 
ot = new Date().getTime(); 
var perload = evt.loaded - oloaded; 
oloaded = evt.loaded;
}

html控件

<progress id="progressBar" value="0" max="100" style="width: 150px;"></progress>

结束语

谢谢大家的持续关注,接下来我将推出ROS机器人系列,聊天机器人系统的作品。大家加油~

举报

相关推荐

0 条评论