使用 multipart/form-data 时,为什么无法正确发送带有 Unicode 的 POST 名称?

2023-11-22

我想发送一个带有附加文件的 POST 请求,尽管某些字段名称中包含 Unicode 字符。但服务器未正确接收它们,如下所示:

>>> # normal, without unicode
>>> resp = requests.post('http://httpbin.org/post', data={'snowman': 'hello'}, files={('kitten.jpg', open('kitten.jpg', 'rb'))}).json()['form']
>>> resp
{u'snowman': u'hello'}
>>>
>>> # with unicode, see that the name has become 'null'
>>> resp = requests.post('http://httpbin.org/post', data={'☃': 'hello'}, files={('kitten.jpg', open('kitten.jpg', 'rb'))}).json()['form']
>>> resp
{u'null': u'hello'}
>>>
>>> # it works without the image
>>> resp = requests.post('http://httpbin.org/post', data={'☃': 'hello'}).json()['form']
>>> resp
{u'\u2603': u'hello'}

我该如何解决这个问题?


从wireshark的评论来看,python-requests 似乎做错了,但可能没有“正确的答案”。

RFC 2388 says

最初采用非 ASCII 字符集的字段名称可以使用 RFC 2047 中描述的标准方法在“name”参数的值内进行编码。

RFC 2047,反过来说

一般来说,“编码字”是一系列可打印的 ASCII 字符,以“=?”开头,以“?=”结尾,中间有两个“?”。它指定了字符集和编码方法,还包括根据该编码方法的规则编码为图形 ASCII 字符的原始文本。

并继续描述“Q”和“B”编码方法。使用“Q”(引用打印)方法,名称将是:

=?utf-8?q?=E2=98=83?=

BUT, as RFC 6266明确指出:

“编码字”不得用在 MIME Con​​tent-Type 或 Content-Disposition 字段的参数中,也不能用在除“comment”或“phrase”之外的任何结构化字段主体中。

所以我们不可以这样做。 (感谢@Lukasa 的这次捕获!)

RFC 2388 还说

也可以提供原始本地文件名,或者作为 “文件名”参数“内容处置:表单数据”之一 标头,或者在多个文件的情况下,在“内容处置: file”子部分的标头。发送应用程序可以提供 文件名;如果发件人操作系统的文件名不是 在 US-ASCII 中,文件名可能是近似的,或者使用 RFC 2231 的方法。

And RFC 2231描述了一种看起来更像您所看到的方法。在里面,

星号(“*”)被重复使用来指示语言和 存在字符集信息并且正在使用编码。 A 单引号(“'”)用于分隔字符集和语言 参数值开头的信息。百分号 (“%”)用作编码标志,符合RFC 2047。

具体来说,参数名称末尾的星号充当 指示字符集和语言信息可能出现在 参数值的开头。单引号用于 将字符集、语言和实际值信息分开 参数值字符串,百分号用于标记 以十六进制编码的八位位组。

也就是说,如果采用此方法(并且两端都支持),则名称应为:

name*=utf-8''%E2%98%83

幸运的是,RFC 5987添加编码基于 RFC 2231到 HTTP 标头! (感谢 @bobince 的发现)它说你可以(任何可能应该)包含 RFC 2231 样式的值and一个简单的值:

头域规范需要定义是否多个实例 允许具有相同 parmname 组件的参数,以及如何 他们应该被处理。该规范建议 使用扩展语法的参数优先。这个会 允许制作者使用两种格式而不破坏接收者 还不明白扩展语法。

Example:

foo:酒吧; title="欧元汇率"; 标题*=utf-8''%e2%82%ac%20exchange%20rates

然而,在他们的例子中,他们“简化”了“遗留客户”的简单价值。这实际上并不是表单字段名称的选项,所以看起来像最好的方法可能是将两者都包括在内 name= and name*=版本,其中纯值(如 @bobince 所描述)“仅以与表单相同的编码发送带引号的字节”,例如:

Content-Disposition: form-data; name="☃"; name*=utf-8''%E2%98%83

也可以看看:

  • Java 中的 HTTP 标头编码/解码
  • 如何根据 RFC 2231 对文件名进行编码?
  • 如何在 HTTP 中对 Content-Disposition 标头的文件名参数进行编码?

最后,看到http://larry.masinter.net/1307multipart-form-data.pdf (also https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909#c8),其中建议通过坚持使用 ASCII 表单字段名称来避免该问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 multipart/form-data 时,为什么无法正确发送带有 Unicode 的 POST 名称? 的相关文章

随机推荐

  • 是否有必要将动态数组的容量加倍?

    当在 C 中创建自动扩展数组 如 C 的 std vector 时 通常 或者至少是常见的建议 在每次填充时将数组的大小加倍 以限制调用的数量realloc为了尽可能避免复制整个数组 例如 我们首先为 8 个元素分配空间 插入 8 个元素
  • BackgroundWorker 中未处理的异常

    我有一个小型 WinForms 应用程序 它利用 BackgroundWorker 对象来执行长时间运行的操作 后台操作偶尔会引发异常 通常是当有人打开正在重新创建的文件时 无论代码是否从 IDE 运行 NET 都会弹出一个错误对话框 通知
  • 为什么我无法在 Rails 中创建数组作为表中的列?

    为什么我不能做这样的事情 class CreateModels lt ActiveRecord Migration def self up create table fruit do t t array apples end end end
  • R:从向量中提取非重复值(不保留重复值)[重复]

    这个问题在这里已经有答案了 我想保留向量中的非重复值 但不保留重复值中的一个元素 unique 对此不起作用 两者都不会重复 例如 gt test lt c 1 1 2 3 4 4 4 5 6 6 7 8 9 9 gt unique tes
  • 如何使用 dcast.data.table 并将公式作为字符串

    我想对 data table 使用强制转换 其中公式的列名作为字符串 我的桌子 c1 c2 c3 1 A 1 1 B 2 1 C 3 2 A1 1 2 B1 2 2 C1 3 我想要的结果是 c1 1 2 3 1 A B C 2 A1 B1
  • 在 C# 中将 Windows 窗体单选按钮与不同的父控件分组

    我有一个 Windows 窗体应用程序 其中有许多单选按钮 这些RadioButtons 被放置在流程布局面板它会自动为我安排它们 所有直接添加到 FlowLayoutPanel 的 RadioButton 都被分组 这意味着我只能选择其中
  • 洋葱架构中的依赖解析

    The 洋葱架构是一种构建应用程序以保持关注点分离和松散耦合的方法 示例项目位于 http onionarch codeplex com 依赖注入 解析是该架构的一个关键方面 因为它用于将所有层连接在一起 上面的链接包含一个有关如何使用 O
  • Java EE前端方法中处理服务层异常

    我维护一个 Web 应用程序 其中有一个带有 JSF 标签的页面
  • 生成 Word 文档时检索组件错误的 COM 类工厂

    我正在尝试从 VB NET 编辑 Word 文档 大部分使用以下代码 如何从 Visual Basic NET 自动创建 Word 来创建新文档 http support microsoft com kb 316383 它在我的机器上运行良
  • Vim 写入时自动命令 - 传递完整文件路径

    我想在 Vim 中保存文件时执行 bash 脚本 问题是我不知道如何才能 或者是否可以传递文件的完整路径 而不仅仅是文件名或打开的相对路径 这是我正在使用的代码 它可以工作 但是只有相对路径 这对我来说毫无用处 autocmd BufWri
  • 升级到 iPhone 3.0 sdk,现在模拟器显示黑屏

    我有一个使用 UITabBarController 的 iPhone 应用程序 其中包含两个 UINavigationController 每个 UINavigationController 又包含一个或多个 TableViewContro
  • 连接简单 x-y 图中的最终点和初始点(绘制闭合曲线/多边形)

    比如说 我有 x 1 1 2 2 y 1 2 2 1 plot x y b 我将得到一个包含连接点 1 1 1 2 和 2 2 的线的图 有没有办法将最后一个点与第一个点连接起来 从而完成绘图上的正方形 我还用点拉入文本行 因此简单地添加另
  • Android 10 (api 29) 中没有此类文件或目录

    我正在开发一个照片编辑器应用程序 在编辑我的图片后 我将其保存到本地存储中 它在 android 9 之前工作正常 但在 android 10 上则不然 它在 Android 10 中显示 找不到此类文件或目录 的异常 经过一些研究 我发现
  • 未找到 Visual Studio 2013 库中的实体框架

    当我尝试使用实体框架时 我在 Visual Studio 2013 的 Visual Basic 中遇到了一个相当不寻常的错误 无论我使用现有项目还是创建新项目 这都无关紧要 当我换了一台装有 Win 8 1 的新电脑时 这种情况就开始发生
  • 将 F# 引用转换为 LINQ 表达式

    我可以转换类型的报价Expr lt a gt b gt 通过以下代码片段连接到 Linq 表达式 Converts a F Expression to a LINQ Lambda let toLambda exp Expr let linq
  • 在 Erlang 中转置二维矩阵

    给定如下所示的矩阵 将其变换 90 度 转换为下面的第二个矩阵 您将如何以最干净的方式做到这一点 首选简短 简洁 清晰的解决方案 其中要点易于掌握 From A1 A2 A3 B1 B2 B3 C1 C2 C3 To A1 B1 C1 A2
  • SQL:选择包含确切给定成员的集

    我确信有一个合适的词来形容这个问题 但我不记得了 但问题很容易描述 我有一个表groupmembers 这是组和成员之间的简单关系 id groupid memberid 1 g1 m1 2 g1 m2 3 g2 m1 4 g2 m2 5
  • Windows Server 2016 上的远程调试 UWP 应用

    The goal 我想使用 Windows Server 2016 x64 来远程调试 UWP 应用程序 原因 我的工作电脑仍然运行 Windows 7 实例 并且无法在 Windows 7 计算机上部署 UWP 应用程序 问题 我已经在
  • Ajax成功后调用函数

    我正在开发一个网站 我们从 XML 文件获取信息 它工作得很好 但现在我需要制作内容的滑块 为此 我将使用 jCarousel 它声称可以通过调用回调函数来动态加载内容 但是 当我成功调用函数时 我无法进行初始 ajax 加载 我究竟做错了
  • 使用 multipart/form-data 时,为什么无法正确发送带有 Unicode 的 POST 名称?

    我想发送一个带有附加文件的 POST 请求 尽管某些字段名称中包含 Unicode 字符 但服务器未正确接收它们 如下所示 gt gt gt normal without unicode gt gt gt resp requests pos