文件下载

假设要下载的文件存放在项目media目录下

最优解:使用FileResponse

import os
from django.http import FileResponse

def file_download(request, file_path):
    response = FileResponse(open(file_path, 'rb')),as_attachment=True,filename="下载File.txt")
    return response

文件名或文件内容里含有中文都没问题,可以正常处理。
注意as_attachmentfilename两个参数只能用karg指定

其他方式

使用HttpResponse

import os
from django.http import HttpResponse

def media_file_download(request, file_path):
    with open(file_path, 'rb') as f:
        response = HttpResponse(f)
        response['content_type'] = "application/octet-stream"
        response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)
        return response

HttpResponse有个很大的弊端,其工作原理是先读取文件,载入内存,然后再输出。如果下载文件很大,该方法会占用很多内存。

使用StreamingHttpResponse

import os
from django.http import StreamingHttpResponse


def file_response_download(request, file_path):
    response = 使用StreamingHttpResponse(open(file_path, 'rb'))
    response['content_type'] = "application/octet-stream"
    response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)
    return response

中文处理

使用“其他方式”下载,若文件名中含有中文则会乱码。解决方法如下:

from django.utils.encoding import escape_uri_path as quote
#下面两行的效果一样,但是不推荐
from urllib.parse import quote
from urllib.request import quote

response['Content-Disposition'] = 'attachment; filename="{}"'.format(quote(name))

文件私有化的两种方法

  1. 上传文件放在media文件夹,文件名使用很长的随机字符串命名(uuid), 让用户无法根据文件名猜出这是什么文件。视图和模板里验证用户是否已登录,登录或通过权限验证后才显示具体的url。- 简单易实现,安全性不高,但对于一般项目已足够。
  2. 上传文件放在非media文件夹,用户即使知道了具体文件地址也无法访问,因为Django只会给media文件夹里每个文件创建独立url资源。视图和模板里验证用户是否已登录,登录或通过权限验证后通过自己编写的下载方法下载文件。- 安全性高,但实现相对复杂。