zoukankan      html  css  js  c++  java
  • python3中用django下载文件,中文名乱码怎么办?

    前段时间被某个前端小可爱鄙视了一下,说我博客都一年不更新了,我不服,明明还有俩月才到一年呢。不过说是这么说,还是要更新一下的。
    以上都是借口,下面开始正文。
     
     
    我公司的某个内部系统,用django做的,项目中不可避免地有下载文件的地方,以前偷懒,我都是用django自带的方法,在项目的总urls.py中使用
     
    urlpatterns += static(FILEPATH, document_root=FILEPATH)
    这种方法解决。
     
    但是这种方法有个极大的缺陷:测试环境写着玩可以,正式环境肯定要把settings中的debug=True关掉的。而这种方法,在关掉debug之后,就不能用了。
     
    于是我只好走传统线路:设置header。
     
    在urls.py中增加:
     
    url(r"^download/$", views.download, name="download")
    在页面中:
     
    <a href="{% url 'download' %}">下载</a>
    在views.py中增加一个视图函数:
     
    def download(request):
        return build_download_response(FILE_PATH, "我爱可乐.docx")
    (MTV模式的程咬金三板斧,没毛病)
     
    由于系统里面不止一个地方用到下载功能,所以,我把它写成了一个通用的函数:
     
    from django.http import FileResponse
     
    def build_download_response(filepath, filename):
        """
        构建下载文件的文件头
        :param filepath: 文件路径
        :param filename: 文件名
        :return: FileResponse
        """
        absname = os.path.join(filepath, filename) if os.path.isdir(filepath) else filepath
     
        response = FileResponse(open(absname, "rb"))
        response["Content-Type"] = "application/octet-stream"
        response["Content-Disposition"] = "attachment; filename='%s'" % filename
        return response
     
    参照网上的说法,这样是没问题的。蓝鹅,它确实出了问题:当我点击下载按钮的时候,弹出的界面只有“下载”二字。
     
     
    喵喵喵?我的文件呢?
    我尝试把文件下载下来看了一下,从大小来看,是没有问题的。
     
     
    我把名字改过来,可以正常打开,里面没有丢东西——换句话说,只是文件名出了问题
    可是文件名能有毛的问题啊?你不能欺负我公司的人只会中文吧!
     
     
     
    经过一番激烈地百度和扣人心弦地搜索,我从这篇博客 https://blog.csdn.net/u011090495/article/details/18815777 里找到了原因。
    简单点说就是,Content-Disposition里面的filename这个东西,原来不是RFC标准,仅支持ASCII编码的文件名。如果文件名不是英文的,恐怕就会出现名字乱码,或者被改名的情况那么怎么办呢?另一个RFC给加上了扩展,可以定义一个filename*,然后把文件名编码一下。
    于是,我把 Content-Disposition 这里从
     
    response["Content-Disposition"] = "attachment; filename='%s'" % filename
    改成了
     
    response["Content-Disposition"] = "attachment; filename='%s'; filename*=UTF-8''%s" % (filename.encode("UTF-8"), filename.encode("UTF-8"))
    结果测试了一下,哭了。
     
     
    还真是编码了……
    我要闹了。
     
    还好,后来又在 https://segmentfault.com/q/1010000009078463 这篇帖子里找到了答案。原来 filename*=UTF-8''%s" % filename.encode("UTF-8") 这样写是不管用的,django自有django的方法:
     
    from django.http import FileResponse
    from django.utils.encoding import escape_uri_path
     
    def build_download_response(filepath, filename):
        """
        构建下载文件的文件头
        :param filepath: 文件路径
        :param filename: 文件名
        :return: FileResponse
        """
        absname = os.path.join(filepath, filename) if os.path.isdir(filepath) else filepath
     
        response = FileResponse(open(absname, "rb"))
        response["Content-Type"] = "application/octet-stream"
        response["Content-Disposition"] = "attachment; filename*=UTF-8''{}".format(escape_uri_path(filename))
     
        return response
     
    于是,就可以正常下载了。
     
     
     
    打开看看,内容完全没问题!
     
     
     
    开心!(我才不会拿去给前端炫耀呢!)
     
  • 相关阅读:
    意图识别及槽填充联合模型bert
    意图识别及槽填充联合模型的改进 cnn-self-attention
    意图识别及槽填充联合模型cnn-seq2seq
    cnn-residual用于意图识别
    centos 8 上配置asp.net core 5
    WPF自定义控件
    jdk 动态代理源码分析
    在windows上构建angular项目 (下)
    在windows上构建angular项目 (上)
    "名字好难想队“团队项目
  • 原文地址:https://www.cnblogs.com/anpengapple/p/11431266.html
Copyright © 2011-2022 走看看