用Django搭建一个文档中转站(云盘)

用户需求

文档的存储和迁移一直是一个troubling问题,特别是在Linux上,现在装了QQ还好,原本没有QQ的时候只能用U盘拷贝。就想着能不能搭个服务器作为中转站,需要哪个文件的的时候发送方先把文件传到服务器上,然后接收方直接去网站上下载。

功能需求

  • 文件上传功能
  • 文件下载功能

实现思路

文件上传so easy,直接用表单提交file即可。但是要注意formenctype属性值,不然会遇到request.FILES为空的问题。

文件下载功能虽然Django可以做到,但是非常繁琐,对于不同类型的文件都要有不同的设置。 刚才看了看FileResponse,发现文件下载还挺简单的。当时我做的时候另辟蹊径,各位看官就随便看看,不过说不定会从中获得一些新的灵感哦~

文件下载功能没有使用Django,而是直接用了 http.server 模块,在控制台直接执行python3 -m http.server就会在当前目录打开一个文件服务器,默认端口号8000。但是这是一个非常简陋的服务器,没有身份验证功能,也就是说知道URL的每个人都可以来下载文件,没有什么安全性可言。
我的想法是可以在Django服务器中设置一个选项,用于开启/关闭 http.server 服务器。但是 http.server 开启之后会独占一个线程,所以不要放在处理请求的函数里,最好是新建一个线程,专门控制 http.server 的开启和关闭。
设置一个全局变量flag,请求函数就通过改变flag的值来控制 http.server 服务器的状态。

def server_switch():
    global flag
    while True:
        res = popen('killhttpserver').read().split('\n')   
        if flag == 0:
            if len(res) > 2:        #如果服务器处于开启状态
                popen('killhttpserver kill 2>tem.log')   #关闭服务器
        else:
            if len(res) <= 2:		#如果服务器处于关闭状态
                popen('cd files;python3 -m http.server 2>tem.log')  #开启服务器
        sleep(1)
t1 = Thread(target=server_switch)
t1.start()

其中popenos模块的函数,其功能是调用shell执行命令,killhttpserver是自己写的脚本,有点小复杂,这里就不细说了,反正实现的功能就是代码段里注释部分写的功能。关于代码中的输出重定向,可以看我的另一边文章—>关于Linux输出重定向的问题。

这样就可以通过改变flag的值控制 http.server 的运行了。

这样虽然简单,但文件服务器的定制性较差,我还是去试试FileResponse吧,学会了再来更新一下 #(&_&)#


分割线


学会FileResponse了,来更新一下。
发现这也太太太简单了吧。

def download(request):
    filename = request.GET['file']
    file = open(filename, 'rb')    
    response = FileResponse(file)
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename='+parse.quote(filename)
    return  response 

open一个file,然后用file初始化FileResponse得到response,将Content-Type属性的值改为application/octet-stream,即二进制传输,不管文件类型。当然这里还有很多别的值可选,比如下载 .jpg的图片可以选image/jpeg.png可以选image/png。有几百种值可选,各种类型应有尽有。不管是哪种类型,反正用application/octet-stream就没错。

服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txtjpg等,会直接在浏览器中显示,而不是下载。如果需要提示用户保存,就要用Content-Disposition进行一下处理,关键在于一定要加上attachmentfilename是指明保存文件的名称但如果文件名含有中文的话,要先用url转码哦,urllib库中的parse.quote函数就可以做到。

然后返回这个response就可以啦。

你可能感兴趣的:(Django,HTML)