方法一: 使用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={0}'.format('test.png')
return response
# response也是一个类似文件的对象,有write等方法
with open(file_path, 'rb') as f:
response = HttpResponse()
response.write(f.read())
response['content_type'] = "application/octet-stream"
response['Content-Disposition'] = 'attachment; filename={0}'.format('test.png')
return response
缺点:其工作原理是先读取文件,载入内存,然后再输出。如果下载文件很大,该方法会占用很多内存。对于下载大文件,Django更推荐StreamingHttpResponse和FileResponse方法。
方法二: 使用SteamingHttpResponse
注意:Django is designed for short-lived requests. Streaming responses will tie a worker process for the entire duration of the response. This may result in poor performance.
Django是为短期请求而设计的。流式响应将在整个响应期间绑定工作进程。这可能导致性能不佳。
import os
from django.http import StreamingHttpResponse
def _file_iterator(file_obj, chunk_size=512):
file_obj.seek(0)
while True:
con = file_obj.read(chunk_size)
if con:
yield con
else:
break
def media_file_download(request, file_path):
with open(file_path, 'rb') as f:
response = StreamingHttpResponse(f)
response['content_type'] = "application/octet-stream"
response['Content-Disposition'] = 'attachment; filename={0}'.format('test.png')
return response
# StreamingHttpResponse还可以接受iterator作为参数
bio = BytesIO()
bio.writer(b'something')
response = StreamingHttpResponse(_file_iterator(bio))
response['content_type'] = "application/octet-stream"
response['Content-Disposition'] = 'attachment; filename={0}'.format('test.png')
return response
方法三: 使用FileResponse
FileResponse是StreamingHttpResponse的子类,并且针对二进制文件做了优化。更推荐用这种方法来下载文件。
接受一个以‘rb’方法打开的文件,并且会自动关闭文件,所以无需使用with上下文管理器打开,或者io.BytesIO()也可以。
import os
from django.http import FileResponse
from werkzeug.wsgi import FileWrapper
def media_file_download(request, file_path):
response = FileResponse(open(file_path, 'rb')) #不需要设置=content_type,FileResponse会自动添加
return response
# 可以接收io.BytesIO对象
buffer = io.BytesIO()
workbook = xlwt.Workbook(encoding='utf-8')
worksheet_1 = workbook.add_sheet('sheet1')
worksheet_1.write(0, 0, label='id')
workbook.save(buffer)
buffer.seek(0)
response = FileResponse(buffer)
#如果生产环境部署在uwsgi下,可能报错,尝试用FileWrapper将文件流转为可迭代对象
response = FileResponse(FileWrapper(buffer), as_attachment=True)
return response