最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • django如何从服务端下载文件到本地

    正文概述    2020-01-10   382

    django如何从服务端下载文件到本地

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

    这里我们将下载的文件存放在项目media目录下,当然在实际中并不会这样做。

    方式一:使用HttpResponse

    import os
    from django.http import HttpResponse, Http404
    def 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 response
           except Exception:
               raise Http404

    HttpResponse有个很大的弊端,其工作原理是先读取文件,载入内存,然后再输出。如果下载文件很大,该方法会占用很多内存。对于下载大文件,Django更推荐StreamingHttpResponse和FileResponse方法,这两个方法将下载文件分批(Chunks)写入用户本地磁盘,先不将它们载入服务器内存。

    方式二:使用StreamingHttpResponse

    import os
    from django.http import HttpResponse, Http404, StreamingHttpResponse
    def 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 response
       except Exception:
           raise Http404

    方式三:使用FileResponse

    import os
    from django.http import HttpResponse, Http404, FileResponse
    def 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 response
       except 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_path
    from .models import Doc
    import requests
    import logging
    logger = 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_url
                doc_url = settings.ITEM_DOMAIN_PORT + doc_url
                try:
                    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 res
            else:
                raise Http404("文档不存在!")

    下载网 » django如何从服务端下载文件到本地

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元