Django(12): 实现文件下载的几种方法

一.使用HttpResponse

 

#直接传入内容
content= b'123456789sdfkjhglbdsjhfjgfb'
response = HttpResponse(content,content_type='application/octet-stream')   #文件流类型
response['Content-Disposition'] = 'attachment; filename={}'.format('2222.txt')     #表示带有文件附件,指定了文件名;浏览器会自动下载
return response

f = open('/data/text.zip','rb')
response = HttpResponse(f,content_type='application/octet-stream')   #文件流类型
response['Content-Disposition'] = 'attachment; filename={}'.format('2222.txt')     #表示带有文件附件,指定了文件名;浏览器会自动下载
return response

弊端:

从以下源码可知,httpresponse对象初始化时会将文件内容载入内存:当文件过大时会大量占用服务器内存

文件下载建议使用下面对象

二.使用SteamingHttpResonse

流类型

import os
from django.http import HttpResponse, Http404, StreamingHttpResponse
 
def stream_http_download(request, file_path):
    try:
        response = StreamingHttpResponse(open(file_path, 'rb'))
        response['content_type'] = "application/octet-stream"
        response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)
        return response
    except Exception:
        raise Http404

 源码:

将传入对象转为迭代器,而不是一次性加载到内存



    def _set_streaming_content(self, value):
        # Ensure we can never iterate on "value" more than once.
        self._iterator = iter(value)
        if hasattr(value, 'close'):
            self._resource_closers.append(value.close)

三.使用FileResponse

为文件传输优化的流类型

import os
from django.http import HttpResponse, Http404, FileResponse
 
 
def file_response_download1(request, file_path):
    try:
        response = FileResponse(open(file_path, 'rb'))
        response['content_type'] = "application/octet-stream"
        response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)
        return response
    except Exception:
        raise Http404
 
 

源码:

迭代器中每次一固定大小读取文件,默认值:block_size = 4096

    def _set_streaming_content(self, value):
        if not hasattr(value, 'read'):
            self.file_to_stream = None
            return super()._set_streaming_content(value)

        self.file_to_stream = filelike = value
        if hasattr(filelike, 'close'):
            self._resource_closers.append(filelike.close)
        value = iter(lambda: filelike.read(self.block_size), b'')
        self.set_headers(filelike)
        super()._set_streaming_content(value)


版权声明:本文为qq_37674086原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。