使用Django生成要下载的文件
是否有可能做一个zip档案,并提供下载,但仍然不保存文件到硬盘驱动器?
要触发下载,您需要设置Content-Disposition
标头:
from django.http import HttpResponse from wsgiref.util import FileWrapper # generate the file response = HttpResponse(FileWrapper(myfile.getvalue()), content_type='application/zip') response['Content-Disposition'] = 'attachment; filename=myfile.zip' return response
如果你不想在磁盘上的文件,你需要使用StringIO
import cStringIO as StringIO myfile = StringIO.StringIO() while not_finished: # generate chunk myfile.write(chunk)
您也可以select设置Content-Length
标题:
response['Content-Length'] = myfile.tell()
你会更快乐地创build一个临时文件。 这节省了大量的内存。 当你有多个或两个用户并发时,你会发现节省内存是非常非常重要的。
但是,您可以写入一个StringIO对象。
>>> import zipfile >>> import StringIO >>> buffer= StringIO.StringIO() >>> z= zipfile.ZipFile( buffer, "w" ) >>> z.write( "idletest" ) >>> z.close() >>> len(buffer.getvalue()) 778
“缓冲区”对象具有778字节的ZIP存档文件。
是的,您可以使用zipfile模块 , zlib模块或其他压缩模块在内存中创buildzip存档。 您可以让视图将zip压缩文件写入Django视图返回的HttpResponse
对象,而不是将上下文发送到模板。 最后,您需要将mimetype设置为适当的格式,以告诉浏览器将响应视为文件 。
为什么不制作一个tar文件呢? 像这样:
def downloadLogs(req, dir): response = HttpResponse(mimetype='application/x-gzip') response['Content-Disposition'] = 'attachment; filename=download.tar.gz' tarred = tarfile.open(fileobj=response, mode='w:gz') tarred.add(dir) tarred.close() return response
models.py
from django.db import models class PageHeader(models.Model): image = models.ImageField(upload_to='uploads')
views.py
from django.http import HttpResponse from StringIO import StringIO from models import * import os, mimetypes, urllib def random_header_image(request): header = PageHeader.objects.order_by('?')[0] image = StringIO(file(header.image.path, "rb").read()) mimetype = mimetypes.guess_type(os.path.basename(header.image.name))[0] return HttpResponse(image.read(), mimetype=mimetype)
def download_zip(request,file_name): filePath = '<path>/'+file_name fsock = open(file_name_with_path,"rb") response = HttpResponse(fsock, content_type='application/zip') response['Content-Disposition'] = 'attachment; filename=myfile.zip' return response
您可以根据您的要求更换邮编和内容types。
与内存中的tgz存档一样:
import tarfile from io import BytesIO def serve_file(request): out = BytesIO() tar = tarfile.open(mode = "w:gz", fileobj = out) data = 'lala'.encode('utf-8') file = BytesIO(data) info = tarfile.TarInfo(name="1.txt") info.size = len(data) tar.addfile(tarinfo=info, fileobj=file) tar.close() response = HttpResponse(out.getvalue(), content_type='application/tgz') response['Content-Disposition'] = 'attachment; filename=myfile.tgz' return response