django——三种方式实现文件下载
在实际的项目中很多时候需要用到下载功能,如导excel、pdf或者文件下载,当然你可以使用web服务自己搭建可以用于下载的资源服务器,如nginx,这里我们主要介绍django中的文件下载。
这里我们将下载的文件存放在项目media目录下,当然在实际中并不会这样做。
方式一:使用HttpResponse
import os
from django.http import HttpResponse, Http404def media_file_download(request, file_path):with open(file_path, 'rb') as f:try:response = HttpResponse(f)response['content_type'] = "application/octet-stream"response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(file_path)return responseexcept Exception:raise Http404
HttpResponse有个很大的弊端,其工作原理是先读取文件,载入内存,然后再输出。如果下载文件很大,该方法会占用很多内存。对于下载大文件,Django更推荐StreamingHttpResponse和FileResponse方法,这两个方法将下载文件分批(Chunks)写入用户本地磁盘,先不将它们载入服务器内存。
方式二:使用StreamingHttpResponse
import os
from django.http import HttpResponse, Http404, StreamingHttpResponsedef 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 responseexcept Exception:raise Http404
方式三:使用FileResponse
import os
from django.http import HttpResponse, Http404, FileResponsedef 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 responseexcept Exception:raise Http404
文件名中文乱码问题
其中用英文的文件名,浏览器显示正常,但是用了中文后,就是默认的文件名,如下载.xls
,或者如果我用了utf-8编码,是乱码。解决方法如下:
response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(name))
文件私有化的两种方法
如果你想实现只有登录过的用户才能查看和下载某些文件,大概有两种方法,这里仅提供思路。
- 上传文件放在media文件夹,文件名使用很长的随机字符串命名(uuid), 让用户无法根据文件名猜出这是什么文件。视图和模板里验证用户是否已登录,登录或通过权限验证后才显示具体的url。- 简单易实现,安全性不高,但对于一般项目已足够。
- 上传文件放在非media文件夹,用户即使知道了具体文件地址也无法访问,因为Django只会给media文件夹里每个文件创建独立url资源。视图和模板里验证用户是否已登录,登录或通过权限验证后通过自己编写的下载方法下载文件。- 安全性高,但实现相对复杂。
个人下载文档view视图代码
from django.views import View
from django.conf import settings
from django.http import FileResponse,Http404
from django.utils.encoding import escape_uri_pathfrom .models import Docimport requests
import logginglogger = logging.getLogger('django')
class Download(View):"""前端传来下载doc的id,后端传给它下载地址"""def get(self,request,doc_id):doc = Doc.objects.only('file_url').filter(is_delete=False,id = doc_id).first()if doc:doc_url = doc.file_urldoc_url = settings.ITEM_DOMAIN_PORT + doc_urltry:res = FileResponse(requests.get(doc_url,stream = True))except Exception as e:logger.info('文件获取异常:{}'.format(e))raise Http404('文件获取异常')file_end = doc_url.split('.')[-1]if not file_end:raise Http404('文档路径出错')else:file_end = file_end.lower()if file_end == "pdf":res["Content-type"] = "application/pdf"elif file_end == "zip":res["Content-type"] = "application/zip"elif file_end == "doc":res["Content-type"] = "application/msword"elif file_end == "xls":res["Content-type"] = "application/vnd.ms-excel"elif file_end == "docx":res["Content-type"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"elif file_end == "ppt":res["Content-type"] = "application/vnd.ms-powerpoint"elif file_end == "pptx":res["Content-type"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation"else:raise Http404("文档格式不正确!")doc_filename = escape_uri_path(doc_url.split('/')[-1])# http1.1 中的规范# 设置为inline,会直接打开# attachment 浏览器会开始下载res["Content-Disposition"] = "attachment; filename*=UTF-8''{}".format(doc_filename)return reselse:raise Http404("文档不存在!")
django——三种方式实现文件下载相关推荐
- 使用apache-poi生成excel文件与同步请求三种方式与文件下载
使用apache-poi生成excel文件 a)添加依赖: <!-- poi依赖--><dependency><groupId>org.apache.poi< ...
- Django中Model继承的三种方式
Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...
- 三种方式让 Android WebView 支持文件下载
三种方式让 Android WebView 支持文件下载 最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk.WebView 默认是不支持下载的,需要开发者自己 ...
- 前端实现文件下载功能的三种方式
一些管理系统常常会有导出文件的功能,这里介绍三种文件下载的尝试 1. 通过文件地址下载文件 此方式最为简易,只需要知道文件在服务器上的地址,就可以通过a标签实现下载 <a href=" ...
- django文件上传到服务器,django上传文件的三种方式
Django文件上传需要考虑的重要事项 文件或图片一般通过表单进行.用户在前端点击文件上传,然后以POST方式将数据和文件提交到服务器.服务器在接收到POST请求后需要将其存储在服务器上的某个地方.D ...
- STM32芯片烧录的三种方式介绍,串口、STM32 ST-LINK Utility以及STM32CubeProgrammer
STM32芯片烧录的三种方式介绍,串口.STM32 ST-LINK Utility以及STM32CubeProgrammer 1 概述 1.1资源概述 1.2 STM32串口烧录方式 2.KEIL软件 ...
- 小程序引入icon的三种方式
小程序引入icon的三种方式(原生图标.WeUI图标组件.iconfont图标) 原生图标 小程序里原生图标是通过icon标签来引入的: <icon type="success&quo ...
- Python实现微信支付(三种方式)
Python实现微信支付(三种方式) 微信.支付宝二维码聚合SDK下载 点我下载 关注公众号"轻松学编程"了解更多. 如果需要python SDk源码,可以加我微信[1257309 ...
- response设置编码的三种方式以及比较
https://blog.csdn.net/u010653908/article/details/53994021 response设置编码的三种方式以及比较 2017年01月03日 14:12:46 ...
- go引入外部依赖的三种方式:go get,go module,vendor目录
本文转载自golang 引入外部包的三种方式:go get, go module, vendor目录_guoguolifang的博客-CSDN博客_golang 外部包 import "g ...
最新文章
- 文档计算机无法分页,同一EXCEL文件在不同计算机上显示分页不同解决办法(6页)-原创力文档...
- Spring boot的@Value注解
- SonarQube4.4+Jenkins进行代码检查实例之三-单元测试分析
- 如何轻松拿到大厂面试offer | 掘金技术征文
- .NET Core 2.1.5和.NET Core SDK 2.1.403发布
- 软考信息安全工程师备考笔记5:第五章应用系统安全基础备考要点
- tomcat通过一个端口号实现多域名访问
- c语言输入n打印数字菱形,打印数字菱形,急啊,帮帮小女子啊。。。
- 001 java_001Java开发环境
- 自学PL/SQL 第一讲decalring variables
- 带你搭建一个H5游戏平台,附源码下载
- 华为身处“创新者的窘境”,而浑然不觉(转载)
- SQL注入-waf绕过
- 再安利几个看片追剧的App
- arcgis 线段合并
- C/C++ 时间知识总结
- linux-web服务
- libco源码解析(2) 创建协程,co_create
- 如何在XP HOME版下设置共享文件夹及其权限?
- idea必备配置和插件