Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 972|回复: 0

flask+gunicorn中文文件下载报错问题及解决

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-7-21 16:20:40 | 显示全部楼层 |阅读模式

    导言

    问题源起与一个静态文件下载的接口:

    from flask import Flask, current_app
    app = Flask(__name__)
    
    @app.route('/file_name')
    def file_download(file_name):
        return send_from_directory(current_app.root_path, file_name)
    

    当file_name中有中文的时候出现内部错误提示:

    UnicodeEncodeError: 'latin-1' codec can't encode characters in position 46-47: ordinal not in range(256)
    

    故障排解

    查找发现发现是中文编码出了问题,需要对响应头进行设置: 参考

    from flask import Flask, current_app,send_from_directory
    app = Flask(__name__)
    
    
    @app.route('/file_name')
    def file_download(file_name):
        res = make_response(send_from_directory(current_app.root_path, file_name, as_attachment=True, conditional=True))
        res.headers["Content-Disposition"] = 'attachment; filename*="utf-8\'\'{}"'.format(file_name.encode().decode('latin-1'))
        return res
    

    这下在本地运行终于可以正常下载了。但放到服务器上用gunicorn部署的时候又出现了问题:

    Traceback (most recent call last):
      File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/workers/sync.py", line 135, in handle
        self.handle_request(listener, req, client, addr)
      File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/workers/sync.py", line 179, in handle_request
        resp.write_file(respiter)
      File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/http/wsgi.py", line 411, in write_file
        if not self.sendfile(respiter):
      File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/http/wsgi.py", line 390, in sendfile
        self.send_headers()
      File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/http/wsgi.py", line 337, in send_headers
        util.write(self.sock, util.to_bytestring(header_str, "ascii"))
      File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/util.py", line 509, in to_bytestring
        return value.encode(encoding)
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 152-157: ordinal not in range(128)
    
    
    

    经过一番查找,又找到了这个网址,参考里面的回答,又将代码改成下面这种形式:

    from urllib.parse import quote
    
    from flask import Flask, current_app,send_from_directory
    
    app = Flask(__name__)
    
    @app.route('/file_name')
    def file_download(file_name):
        res = make_response(send_from_directory(current_app.root_path, file_name, as_attachment=True, conditional=True))
        res.headers["Content-Disposition"] = 'attachment; filename={}"'.format(quote(file_name))
        return res
    

    这下终于成功下载中文文件名的文件了。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 11:48 , Processed in 0.056647 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表