以django导出xlsx文件为例: Django 提供三种方式实现文件下载功能,分别是:HttpResponse、StreamingHttpResponse和FileResponse
数据来源
import openpyxl
from io import BytesIO
file_handler = openpyxl.Workbook()
writer = file_handler.active
writer.append(("name", "age"))
for i in range(10):
writer.append(("1", "21"))
buffer = BytesIO()
file_handler.save(buffer)
file_handler.close()
三种方式对比
-
HttpResponse 是所有响应过程的核心类,它的底层功能类是HttpResponseBase。 -
StreamingHttpResponse 是在HttpResponseBase 的基础上进行继承与重写的,它实现流式响应输出(流式响应输出是使用Python的迭代器将数据进行分段处理并传输的),适用于大规模数据响应和文件传输响应。 -
FileResponse 是在StreamingHttpResponse 的基础上进行继承与重写的,它实现文件的流式响应输出,只适用于文件传输响应。 -
HttpResponse 实现文件下载存在很大弊端,其工作原理是将文件读取并载入内存,然后输出到浏览器上实现下载功能。如果文件较大,该方法就会占用很多内存。对于下载大文件,Django推荐使用5. StreamingHttpResponse 和FileResponse 方法,这两个方法将下载文件分批写入服务器的本地磁盘,减少对内存的消耗。 -
StreamingHttpResponse 和FileResponse 的实现原理是相同的,两者都是将下载文件分批写入本地磁盘,实现文件的流式响应输出。 -
从适用范围来说,StreamingHttpResponse 的适用范围更为广泛,可支持大规模数据或文件输出,而FileResponse 只支持文件输出。 -
从使用方式来说,由于StreamingHttpResponse 支持数据或文件输出,因此在使用时需要设置响应输出类型和方式,而FileResponse只需设置3个参数即可实现文件下载功能。
httpResponse
普通例子
def download1(request):
file_path = r"E:\myDjango\file\1.jpg"
try:
r = HttpResponse(open(file_path,"rb"))
print(r)
r["content_type"]="application/octet-stream"
r["Content-Disposition"]="attachment;filename=1.jpg"
return r
except Exception:
raise Http404("Download error")
xlsx:
def make_res1(buffer):
response = HttpResponse(content_type="application/octet-stream")
response["Content-Disposition"] = 'attachment;filename="122.xlsx"'
response.write(buffer.getvalue())
return response
StreamingHttpResponse
普通例子
def download2(request):
file_path = r"E:\myDjango\file\2.jpg"
try:
r = StreamingHttpResponse(open(file_path,"rb"))
r["content_type"]="application/octet-stream"
r["Content-Disposition"]="attachment;filename=2.jpg"
return r
except Exception:
raise Http404("Download error")
bytesIo
def yield_buffer(buffer):
buffer.seek(0)
for line in buffer:
yield line
def make_res2(buffer):
response = StreamingHttpResponse(yield_buffer(buffer))
response['Content-Type'] = 'application/octet-stream'
response["Content-Disposition"] = 'attachment;filename="122.xlsx"'
return response
FileResponse
普通例子
def download3(request):
file_path = r"E:\myDjango\file\3.jpg"
try:
f = open(file_path,"rb")
r = FileResponse(f,as_attachment=True,filename="3.jpg")
return r
except Exception:
raise Http404("Download error")
bytesIO
def make_res3(buffer):
response = FileResponse(yield_buffer(buffer))
response.write()
response['Content-Type'] = 'application/octet-stream'
response["Content-Disposition"] = 'attachment;filename="122.xlsx"'
return response
drf的Response
会报错,Response还是用与ApiResponse返回比较好。
|