前言:
最近工作中需要使用django實(shí)現(xiàn)文件的下載功能展鸡。自己通過file.read方式實(shí)現(xiàn)后埃难,在測(cè)試的過程中,發(fā)現(xiàn)當(dāng)文件過大時(shí)忍弛,非常吃內(nèi)存考抄,為了優(yōu)化 在網(wǎng)上找了一篇非常不錯(cuò)的文章解決了該問題!
- django版本:1.8.2
- python版本:2.7.10
參考文章的出處:http://www.reibang.com/p/2ce715671340
實(shí)現(xiàn)思路詳解:
1.使用了django的StreamingHttpResponse對(duì)象疯兼,以文件流的方式下載文件;
2.使用了迭代器(file_iterator()方法),將文件進(jìn)行分割啦鸣,避免消耗過多內(nèi)存来氧;
3.添加響應(yīng)頭:Content-Type 和 Content-Disposition,讓文件流寫入硬盤
代碼:
# coding:utf-8
import json
import os
import traceback
import time
from django.http import HttpResponse
from django.http import StreamingHttpResponse
from rest_framework import viewsets
from rest_framework.decorators import list_route
class ExportFile(viewsets.GenericViewSet):
@staticmethod
def file_iterator(download_file, chunk_size=1024):
with open(download_file) as f:
while True:
c = f.read(chunk_size)
if c:
yield c
else:
break
@list_route(methods=["GET"])
def download(self, request):
"""下載"""
file_path = "需要下載的文件路徑"
if not os.path.exists(file_path):
raise IOError("file not found!")
try:
file_name = os.path.basename(file_path)
file_name = "{file_name}_{timestamp}".format(file_name=file_name, timestamp=int(time.time()))
response = StreamingHttpResponse(self.file_iterator(file_path))
response["Content-Type"] = "application/octet-stream"
response["Content-Disposition"] = "attachment;filename={}".format(file_name)
return response
except Exception as e:
logger.error(e.message)
logger.error(traceback.format_exc())
return HttpResponse(json.dumps({"success": False, "error": u"下載文件失敗"}), status=500,
content_type="text/json")