django提供文件下载时,若果文件较小,解决办法是先将要传送的内容全生成在内存中,然后再一次性传入Response对象中:

def simple_file_download(request):
# do something...
content = open("simplefile", "rb").read()
return HttpResponse(content)

如果文件非常大时,最简单的办法就是使用静态文件服务器,比如Apache或者Nginx服务器来处理下载。不过有时候,我们需要对用户的权限做一下限定,或者不想向用户暴露文件的真实地址,或者这个大内容是临时生成的(比如临时将多个文件合并而成的),这时就不能使用静态文件服务器了。

django文档中提到,可以向HttpResponse传递一个迭代器,流式的向客户端传递数据。

要自己写迭代器的话,可以用yield:

def read_file(filename, buf_size=8192):
with open(filename, "rb") as f:
while True:
content = f.read(buf_size)
if content:
yield content
else:
break
def big_file_download(request):
filename = "filename"
response = HttpResponse(read_file(filename))
return response

或者使用生成器表达式,下面是django文档中提供csv大文件下载的例子:

import csv

from django.utils.six.moves import range
from django.http import StreamingHttpResponse class Echo(object):
"""An object that implements just the write method of the file-like
interface.
"""
def write(self, value):
"""Write the value by returning it, instead of storing in a buffer."""
return value def some_streaming_csv_view(request):
"""A view that streams a large CSV file."""
# Generate a sequence of rows. The range is based on the maximum number of
# rows that can be handled by a single sheet in most spreadsheet
# applications.
rows = (["Row {0}".format(idx), str(idx)] for idx in range(65536))
pseudo_buffer = Echo()
writer = csv.writer(pseudo_buffer)
response = StreamingHttpResponse((writer.writerow(row) for row in rows),
content_type="text/csv")
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
return response

python也提供一个文件包装器,将类文件对象包装成一个迭代器:

class FileWrapper:
"""Wrapper to convert file-like objects to iterables""" def __init__(self, filelike, blksize=8192):
self.filelike = filelike
self.blksize = blksize
if hasattr(filelike,'close'):
self.close = filelike.close def __getitem__(self,key):
data = self.filelike.read(self.blksize)
if data:
return data
raise IndexError def __iter__(self):
return self def next(self):
data = self.filelike.read(self.blksize)
if data:
return data
raise StopIteration

使用时:

from django.core.servers.basehttp import FileWrapper
from django.http import HttpResponse
import os
def file_download(request,filename): wrapper = FileWrapper(open(filename, 'rb'))
response = HttpResponse(wrapper, content_type='application/octet-stream')
response['Content-Length'] = os.path.getsize(path)
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response

django也提供了StreamingHttpResponse类来代替HttpResponse对流数据进行处理。

压缩为zip文件下载:

import os, tempfile, zipfile
from django.http import HttpResponse
from django.core.servers.basehttp import FileWrapper
def send_zipfile(request):
"""
Create a ZIP file on disk and transmit it in chunks of 8KB,
without loading the whole file into memory. A similar approach can
be used for large dynamic PDF files.
"""
temp = tempfile.TemporaryFile()
archive = zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED)
for index in range(10):
filename = __file__ # Select your files here.
archive.write(filename, 'file%d.txt' % index)
archive.close()
wrapper = FileWrapper(temp)
response = HttpResponse(wrapper, content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=test.zip'
response['Content-Length'] = temp.tell()
temp.seek(0)
return response

不过不管怎么样,使用django来处理大文件下载都不是一个很好的注意,最好的办法是django做权限判断,然后让静态服务器处理下载。

这需要使用sendfile的机制:"传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应用程序内存,然后再把内存当中的内容发送给客户端浏览器。这种方式在应付当今大负载网站会消耗更多的服务器资源。sendfile是现代操作系统支持的一种高性能网络IO方式,操作系统内核的sendfile调用可以将文件内容直接推送到网卡的buffer当中,从而避免了Web服务器读写文件的开销,实现了“零拷贝”模式。 "

Apache服务器里需要mod_xsendfile模块来实现,而Nginx是通过称为X-Accel-Redirect的特性来实现。

nginx配置文件:

# Will serve /var/www/files/myfile.tar.gz
# When passed URI /protected_files/myfile.tar.gz
location /protected_files {
internal;
alias /var/www/files;
}

或者

# Will serve /var/www/protected_files/myfile.tar.gz
# When passed URI /protected_files/myfile.tar.gz
location /protected_files {
internal;
root /var/www;
}

注意alias和root的区别。

django中:

response['X-Accel-Redirect']='/protected_files/%s'%filename

这样当向django view函数发起request时,django负责对用户权限进行判断或者做些其它事情,然后向nginx转发url为/protected_files/filename的请求,nginx服务器负责文件/var/www/protected_files/filename的下载:

@login_required
def document_view(request, document_id):
book = Book.objects.get(id=document_id)
response = HttpResponse()
name=book.myBook.name.split('/')[-1]
response['Content_Type']='application/octet-stream'
response["Content-Disposition"] = "attachment; filename={0}".format(
name.encode('utf-8'))
response['Content-Length'] = os.path.getsize(book.myBook.path)
response['X-Accel-Redirect'] = "/protected/{0}".format(book.myBook.name)
return response

  

 

Django 大文件下载的更多相关文章

  1. django 实现文件下载功能

    一.概述 在实际的项目中很多时候需要用到下载功能,如导excel.pdf或者文件下载,当然你可以使用web服务自己搭建可以用于下载的资源服务器,如nginx,这里我们主要介绍django中的文件下载. ...

  2. 【技术博客】Django中文件下载的实现

    开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. Django中文件下载的实现 1.背景 在VisualPy ...

  3. ASP.NET 大文件下载的实现思路及代码

    文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代 ...

  4. 2016 - 1- 24 大文件下载 关于NSOutStream 的使用补充

    // // ViewController.m // 大文件下载 // // Created by Mac on 16/1/24. // Copyright © 2016年 Mac. All right ...

  5. 网络编程---(数据请求+slider)将网络上的大文件下载到本地,并打印其进度

    网络编程---将网络上的大文件下载到本地,并打印其进度. 点击"開始传输"button.将网络上的大文件先下载下来,下载完毕后,保存到本地. UI效果图例如以下: watermar ...

  6. OC - 16.大文件下载

    大文件下载注意事项 若不对下载的文件进行转存,会造成内存消耗急剧升高,甚至耗尽内存资源,造成程序终止. 在文件下载过程中通常会出现中途停止的状况,若不做处理,就要重新开始下载,浪费流量. 大文件下载的 ...

  7. .net Mvc文件下载的功能,大文件下载完成之后修改数据库功能

    原文:.net Mvc文件下载的功能,大文件下载完成之后修改数据库功能 我服务器上文件只能下载一次,下载了之后就不能下载了,大文件或网速不好时,可能服务端文件流发送完了,客户端还没下载完,导致下载失败 ...

  8. iOS开发-大文件下载与断点下载思路

    大文件下载方案一:利用NSURLConnection和它的代理方法,及NSFileHandle(iOS9后不建议使用)相关变量: @property (nonatomic,strong) NSFile ...

  9. PHP实现大文件下载

    实现大文件下载的关键在于循环读取字节流 function downloadFile($filename) { //获取文件的扩展名 $allowDownExt = array ( 'rar', 'zi ...

随机推荐

  1. openerp模块收藏 auto_setup 自动帮你完成建新库时必做几个操作(转载)

    auto_setup 自动帮你完成建新库时必做几个操作 原文:http://shine-it.net/index.php/topic,6777.0.html 模块地址: https://github. ...

  2. itertools模块速查

    学习itertools模块记住这张表就OK了 参考:http://docs.python.org/2/library/itertools.html#module-itertools Infinite ...

  3. 谈网页游戏外挂之用python模拟游戏(热血三国2)登陆

    看web看多了,想写写页游的外挂,其实原理是一样的,就是端口不一样协议字段你不知道,而这也提高了点技术门槛,看我们来一点一点突破这些门槛,这次我们来用python发包模拟flash的客户端登陆. 以热 ...

  4. apache-tomcat-9安装以及与eclipse结合

    apache-tomcat-下载:http://tomcat.apache.org/download-90.cgi 安装(转载):http://jingyan.baidu.com/article/60 ...

  5. SVN的405错误

    错误1: 如果你没有阅读以下文字,活该你倒霉(这段文字是在googlecode添加新项目时生成的): Command-line access If you plan to make changes, ...

  6. IR的评价指标—MAP,NDCG,MRR

    http://www.cnblogs.com/eyeszjwang/articles/2368087.html MAP(Mean Average Precision):单个主题的平均准确率是每篇相关文 ...

  7. 【转载】hadoop的版本问题

    免责声明:     本文转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除.     原文作者:阿笨猫      原文地址:http://www.cnblogs.com/xu ...

  8. (ASP.NET)C#连接Oracle数据库示例(中文乱码问题解决)

    接手了一个遗留的ASP.NET系统,数据库用的是Oracle,以前没搞过.NET和Oracle数据库,数据库搞了半天才解决乱码问题,在此做个笔记备忘. 1.下载安装ODAC 1)请去Oracle官网下 ...

  9. 几款实用的 JavaScript 图形图表库

    一款好的图表插件不是那么容易找到的.最近项目里需要实现统计图表功能,所以在网上搜罗了一圈,找到一些不错的图表插件,分享大家.众多周知,图形和图表要比文本更具表现力和说服力.这里给大家精心推荐几款实用的 ...

  10. hbase操作的问题

    写了一个java程序,需要向hbase中写入大量的数据,但是这个程序执行一半就报错, 问题是,此时已经写入了很多数据. 查看jps,发现hmaster进程崩溃了. 基于以上信息,发现是在程序中,链接h ...