Django 1.11下载文件chunk by chunk

时间:2017-04-24 14:55:41

标签: python django download streaming

就我而言,我将Django 1.11服务器作为代理。当您从浏览器中单击“下载”时,它会向django代理发送一个请求,该代理从另一个服务器下载文件并对其进行处理,之后他们必须将它们“发送”到浏览器以允许用户下载它们。我的代理按块分下载并处理文件块。 如何在准备好时将块发送到浏览器,以便用户最终下载单个文件?

在实践中,我必须让你下载一个尚未就绪的文件,比如一个流。

def my_download(self, res)

   # some code
   file_handle = open(local_path, 'wb', self.chunk_size)

   for chunk in res.iter_content(self.chunk_size):
        i = i+1
        print("index: ", i, "/", chunks)
        if i > chunks-1:
            is_last = True

        # some code on the chunk

        # Here, instead of saving the chunk locally, I would like to allow it to download it directly.
        file_handle.write(chunk)
    file_handle.close()

    return True

提前谢谢你,问候。

1 个答案:

答案 0 :(得分:5)

此问题应标记为此帖的重复:Serving large files ( with high loads ) in Django

请在SO中创建问题之前尝试找到答案!

基本上答案包含在Django的文档:"Streaming Large CSV files"示例中,我们将上述问题应用到该示例中:

您可以使用Django的StreamingHttpResponse和Python的wsgiref.util.FileWrapper来有效地提供大块文件,而无需将其加载到内存中。

def my_download(request):
    file_path = 'path/to/file'
    chunk_size = DEFINE_A_CHUNK_SIZE_AS_INTEGER
    filename = os.path.basename(file_path)

    response = StreamingHttpResponse(
        FileWrapper(open(file_path, 'rb'), chunk_size),
        content_type="application/octet-stream"
    )
    response['Content-Length'] = os.path.getsize(file_path)    
    response['Content-Disposition'] = "attachment; filename=%s" % filename
    return response

现在,如果你想对chunk-by-chunk文件应用一些处理,你可以利用FileWrapper's生成的迭代器:

将块处理代码放在必须返回块的函数中:

def chunk_processing(chunk):
    # Process your chunk here
    # Be careful to preserve chunk's initial size. 
    return processed_chunk

现在在StreamingHttpResponse

中应用该功能
response = StreamingHttpResponse(
    (
        process_chunk(chunk) 
        for chunk in FileWrapper(open(file_path, 'rb'), chunk_size
    ),content_type="application/octet-stream"
)