zoukankan      html  css  js  c++  java
  • Flask下如何处理Requests 上传中文文件名的问题

    一、问题的由来

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

    clip_image002

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

    二、代码解析

            客户端测试代码:

    image

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

            服务端代码(简化后):

    image

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

         运行:

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

    clip_image002

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

    clip_image004

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

    三、问题缘由的查找

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

    clip_image002[5]

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

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

    image

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

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

    clip_image002[7]

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

    四、解决办法

    有三种解决办法。

    (1.)修改Requests的源代码

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

    image

    改成

    image

    (2.)修改Flask的源代码

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

    image

    改成

    image

    并导入相应的包。

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

    clip_image002[9]

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

  • 相关阅读:
    【Educational Codeforces Round 33 B】Beautiful Divisors
    【Educational Codeforces Round 33 A】Chess For Three
    【习题 6-7 UVA
    【习题 6-6 UVA
    【习题 6-5 UVA-1600】Patrol Robot
    【习题 6-4 UVA-439】Knight Moves
    【习题 6-3 UVA
    【POJ1144】Network(割点)(模板)
    【CF711D】Directed Roads(环,强连通分量)
    【CF711C】Coloring Trees(DP)
  • 原文地址:https://www.cnblogs.com/liaofeifight/p/5807901.html
Copyright © 2011-2022 走看看