zoukankan      html  css  js  c++  java
  • Django 实现下载功能时中文文件名问题

    先上最终解决代码(有待验证各浏览器效果):

    def download_file(request, file_path):
        file_name = os.path.basename(file_path)
        if not os.path.isfile(file_path):
            return HttpResponse(file_name)
    
        def file_iterator(tar_file_path, chunk_size=512):
            with open(tar_file_path, mode='rb') as file:
                while True:
                    content = file.read(chunk_size)
                    if content:
                        yield content
                    else:
                        break
    
        try:
            response = StreamingHttpResponse(file_iterator(file_path))
            response['Content-Type'] = 'application/octet-stream'response["Content-Disposition"] = "attachment; filename*=UTF-8''{}".format(escape_uri_path(file_name))
    except:
            return HttpResponse("Sorry but Not Found the File")
    
        return response

    重点在于黄色记号笔标注的那行代码。
    网上大多资料都是这么写的:

    response['Content-Disposition'] = 'attachment;filename="{}"'.format(file_name)

    这种写法对应纯英文的文件名是没有问题的,因为 Content-Disposition 里面的 filename ,不是RFC标准,仅支持ASCII编码的文件名。如果文件名不是英文的,就会出现名字乱码,或者被改名的情况。

    如何直接采用解码的方式也还是会出现byte数组的文件名:

    response['Content-Disposition'] = 'attachment;filename="{}"'.format(file_name.encode('utf8'))

    得到的结果类似于这样:b'-xc6-xbd-xcc-xa8-xc4-xda-xb2-xbf-xb2-xe2-xca-xd4.xlsx' (3).xls

    原因是不同浏览器对于下载文件文件名的编码解析格式不一样,常用浏览器解析格式如下:

    • IE浏览器,采用URLEncoder编码
    • Opera浏览器,采用filename*方式
    • Safari浏览器,采用ISO编码的中文输出
    • Chrome浏览器,采用Base64编码或ISO编码的中文输出
    • FireFox浏览器,采用Base64或filename*或ISO编码的中文输出

    如果硬来的话就是在后台把文件名先 encode 成 bytes,再判断浏览器,根据不同的浏览器用相应的编码decode一下就好了
    例如浏览器是FireFox,后台编码是 utf-8,则进行如下操作

    response['Content-Disposition'] = 'attachment; filename=' + filename.encode('utf-8).decode('ISO-8859-1')
  • 相关阅读:
    SpringMVC之文件上传
    Spring之jdbc【继承JdbcDaoSupport】
    Spring中jdbcTemplate的用户实例
    SpringMVC之数据存储
    SpringMVC的日期转换
    SpringMVC配置解决中文乱码的过滤器
    【对数据库操作的封装成工具类之jdbc】
    实现用户注册与登入功能的案例
    【反射之Field】获取字段
    Can't get WebApplicationContext object from ContextRegistry.GetContext(): Resource handler for the 'web' protocol is not defined
  • 原文地址:https://www.cnblogs.com/zoneofmine/p/11532457.html
Copyright © 2011-2022 走看看