【问题标题】:To Understand More about Encoding U+30C9 vs U+30C8U+3099了解有关编码 U+30C9 与 U+30C8U+3099 的更多信息
【发布时间】:2022-01-29 14:09:55
【问题描述】:

ド(U+30C9) vs ド(U+30C8U+3099)

仅供参考,情况是

  1. 用户从 Web 应用程序将名称包含 ド(U+30C8U+3099) 的文件上传到 AWS s3。
  2. 然后,网站向 AWS lambda 函数发送了一个 POST 请求,其中包含没有 url 编码的文件名,以便使用 Python 进行进一步处理。到达 Lambda 时的名称变成了ド(U+30C9)。然后由于 unicode 的不同,Python 无法访问存储在 s3 中的文件。

我认为解决方案是在发送请求之前在前端进行 url 编码,并使用 urllib.parse.unquote 进行 url 解码以获得相同的 unicode。

我的问题是

  1. url 编码能解决这个问题吗?我无法重现同样的问题,可能是因为我使用的操作系统与用户的操作系统不同。

  2. 自从两个请求(上传到 s3 并将第二个请求发送到 lambda)都发生在用户的机器上之后,究竟发生了什么?

谢谢。

【问题讨论】:

标签: utf-8 character-encoding


【解决方案1】:

您遇到了一个常见情况(可能在拉丁文字中更常见):规范等价。 Unicode 要求以相同的方式处理规范等价序列。

如果你查看 UnicodeData.txt 你会发现:

30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;;
30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;;

因此,30C9 规范等效于 30C8 3099。

通常,最好将 Unicode 字符串标准化为常见的规范形式。不幸的是,我们有其中两个:NFC 和 NFD:规范化形式规范组合和规范化形式规范分解。 Apple 更喜欢后者(Unicode 最初的设计/偏好是关于这种形式),而大多数其他供应商都是第一个。

所以不要相信网络浏览器会保持相同的表单。但也要考虑到用户端的输入法可能会给您带来不同的变化(对于键盘,您可能还有非规范的形式,应该规范化[这可能发生在几个组合字符中])。

因此,在您的后端,您应该选择一种规范化形式,并以这种形式转换所有输入数据(或者只是确保所有搜索和比较函数都可以正确处理等效序列,但这需要在每次调用时进行规范化,所以它可能效率较低)。

Python 有 unicodedata.normalize()(在标准库中,请参阅 unicodedata module),用于规范化 Unicode 字符串。最终,在其他语言上,您应该使用 ICU 库。在任何情况下,您都应该规范化 Unicode 字符串。

注意:这与编码无关,但它直接内置于 Unicode 设计中。原因是要求与旧编码兼容,旧编码有两种方式来描述相同的字符。

【讨论】:

  • 我明白了。感谢您的解释。我想我也应该在前端使用 JavaScript 进行规范化,因为文件输入直接发送到我无法控制的云服务?然后,我可以在后端使用相同的规范形式从云服务存储中检索它。
  • 我认为这是一种明智的方式。只考虑安全隐患(可能没有),前端无法访问后端的所有页面,或者某些客户端进行不一致的调用(一种形式的授权,以及与另一种形式的连接)
猜你喜欢
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
  • 2018-04-15
  • 1970-01-01
  • 2018-07-17
相关资源
最近更新 更多