一、问题的由来

    最近有个项目,叫做文档服务资源中心,类似于七牛,为各个业务系统提供统一的文件资源服务,包括文件的存储、操作管理、下载、预览等。在做文件存储的时候,遇到了这个当指定上传的文件名为中文时,Flask框架的服务端无法解析成文件,而是当成一般的表单数据处理。我们在文件存储的实现架构如下图:

        客户端业务系统(Python开发的)通过调用python-sdk中的上文文件API上传文件。按照requests这个类库上传文件的格式要求,必须指明文件的文件名。所以,在API开发完成之后,当上传的文件的文件名是中文的时候,测试没通过。

 

二、代码解析

        客户端测试代码:

 

     请注意,在files变量中,file对应的元组值的第一个参数“十三五”发展规划.docx”就是文件名,是中文格式。

        服务端代码(简化后):

           注意,在try..exception中的代码,判断是否获取文件成功。

     运行:

         先运行服务端代码,然后运行测试代码。结果如下:

          进入调试模式,查看request变量的值,重点关注files跟form属性。如下图:

      从上图可以,files的属性为空,而把file当成了form数据的属性,属性的值为文件的二进制内容数据。

三、问题缘由的查找

 

(1.)下载fiddler抓包工具。发现requests向flask网站服务传递如下数据。

特别注意,红框中的filename*这一段。

(2.)读Flask的源代码,特别注意Flask对上传文件的解析与处理。发现位于werkzeug下的formparser.py里的parse_lines方法中判断语句(位于文件的413行)

        可以得出结论,Flask是根据名称为filename的键来判断Requests传递过来的数据是否是文件内容。而在上面通过fiddler抓包工具可知,Requests传递了filename*这个键的名称,多了一个*号。所以,Flask认为不是传递的文件,从而当成了一般属性处理。

(3.)那Requests为什么会传递filename*这样的键呢。再次跟踪并阅读Requests的源代码。返现Requests会对filename做编码的特殊处理。代码位于requestsàpackagesàurllib3—>fields.py(第22行的format_header_param方法)。

     对不是ascii编码的内容,进行了rfc 2231编码,并组织成key*= rfc 2231这种格式。所以就有了上述的filename*这种格式的键值对。

四、解决办法

有三种解决办法。

(1.)修改Requests的源代码

requestsàpackagesàurllib3—>fields.py—>format_header_param方法的以下代码

改成

(2.)修改Flask的源代码

werkzeug下的formparser.py里的parse_lines方法中的413行开始的以下代码

改成

并导入相应的包。

 

(3.)修改调用Request的post方法时files变量的filename赋值,将其改成英文,比如设置成固定的file_name,而将真正的filename(最好带有后缀)当成data参数中的键名为file_name(根据项目情况,自由定义)的值传递给服务端,服务端去读取file_name对应的值就行。实现代码如下:

      总结:修改Flask、requests类库的源代码不太理想,不便于部署,而且可能会发生其他意想不到的问题。建议采用第3中折中解决办法。

Flask下如何处理Requests 上传中文文件名的问题的更多相关文章

  1. 完美解决ExtJs6上传中文文件名乱码,后端SpringMVC

    ExtJs上传中文文件名乱码,观察请求. ExtJs6上传乱码从后台无法解决,因为文件名请求里面就已经乱码了,后台无法解码. 除非请求参数正确没有乱码,后台因为编码设置不一样,可以通过后台处理乱码 这 ...

  2. PHP 中move_uploaded_file 上传中文文件名失败

    项目需要上传文件名保持不变,发现上传中文失败:错误如下: move_uploaded_file(public/upload/files//-/\开密二次开发.rar): failed to open ...

  3. requests 上件中文文件名报错解决方案

    这几天在用wxpy写机器人,在调用里面的上传文件接口的时候,一直报错.经过排查后,发现是不支持中文文件名:在群里问了下作者后才知道是requests惹的祸,默认requests用的是unicode来处 ...

  4. php 解决上传中文文件名时出现乱码的问题

    有时候上传文件是中文的文件名会出现乱码, 可以在移动文件时使用icov('utf-8','gb2312',filename)转换 代码: <?php //header('Content-type ...

  5. Servlet 起航 文件上传 中文文件名下载

    @WebServlet(name = "ticketServlet",urlPatterns = {"/tickets"},loadOnStartup = 1) ...

  6. Java中FTPClient上传中文目录、中文文件名乱码问题解决方法【好用】

    转: Java中FTPClient上传中文目录.中文文件名乱码问题解决方法 问题描述: 使用org.apache.commons.net.ftp.FTPClient创建中文目录.上传中文文件名时,目录 ...

  7. php上传中文文件文件名乱码问题

    php上传文件是最最基础的一个技术点,但是深入进去也有不少问题需要解决,这不,上传中文文件后,文件名变成了乱码. 下面是问题代码,很简单: 1.问题代码 html部分: <html> &l ...

  8. ueditor 1.4.3 gbk asp 上传中文乱码 终极解决方法 ie6 ie8 也适用

    [摘要:百度编纂器1.43 gbk asp 题目 1.firefox3.0下 单图上传 面没有了 面多图上传 中央的蓝色按钮(即 面击挑选图片)没有表现(附件上传出那个题目) 没有晓得我的水狐吃翔了 ...

  9. requests上传文件

    """ requests上传文件时,如果文件名是中文,会导致上传失败,参考:https://www.cnblogs.com/liaofeifight/p/5807901. ...

随机推荐

  1. 项目vue2.0仿外卖APP(五)

    header组件 vue-resourse应用 https://github.com/pagekit/vue-resource vue-resource是Vue.js的一款插件,它可以通过XMLHtt ...

  2. 大型App要搞的几个系统

    路由模块: 解耦各个业务,统一收敛页面跳转,动态决策跳转实现:   鉴权模块:收敛鉴权项目(比如登录.输入密码.短信验证.扫脸),后台动态控制鉴权项目:   收银台:收敛支付,统一到收银台:   开关 ...

  3. js数组中sort排序注意的地方

    var a=[1,2,3,4,5] function sum(a,b) { return a-b } //从小到大 function obj(a,b) { return b-a } //从大到小 a. ...

  4. airflow 部署

    环境 : ubuntu 14.04 LTS python 2.7 script: 设置环境变量: export AIRFLOW_HOME=~/airflow 安装相关依赖包: sudo apt-get ...

  5. C#操作access和SQL server数据库代码实例

    在C#的学习中,操作数据库是比较常用的技术,而access和sql server 数据库的操作却有着不同.那么,有哪些不同呢? 首先,需要引用不同的类.因为有着不同的数据引擎. access:usin ...

  6. Fabric远程自动化使用说明

    背景: 关于Fabric的介绍,可以看官网说明.简单来说主要功能就是一个基于Python的服务器批量管理库/工具,Fabric 使用 ssh(通过 paramiko 库)在多个服务器上批量执行任务.上 ...

  7. 排序之----插入排序(C#实现)

    算法步骤:(从小到大) 1:将第一个元素与第二个元素比较大小,如果第一个元素小于等于第二个元素,不做处理,继续比较第二个元素和第三个元素. 如果第三个元素小于第二个元素,保存要移动的元素(第三个元素) ...

  8. css-关于文本

    1. 使用 text-overflow:ellipsis; 超出部分会变成省略号 http://www.w3school.com.cn/tiy/t.asp?f=css3_text-overflow 1 ...

  9. apk逆向 - smali动态调试

    author: Dlive date: 2016/10/6 0x00 前言 ​ 之前有人问过smali的动态调试方法,其实网上已经有很多文章讲这些内容,但是为了方便大家学习,我还是写一下让大家少走点坑 ...

  10. Android JNI总结

    @Dlive 0x01 JNI介绍 JNI是Java Native Interface的缩写,JNI不是Android专有的东西,它是从Java继承而来,但是在Android中,JNI的作用和重要性大 ...