【问题标题】:Handle non-ASCII filenames in XHR uploading在 XHR 上传中处理非 ASCII 文件名
【发布时间】:2013-10-08 16:54:41
【问题描述】:

我有相当标准的 javascript/XHR 拖放文件上传代码,只是遇到了一个不幸的现实世界障碍。我的(Win7)桌面上有一个名为“TEST-é-TEST.txt”的文件。在 Chrome (30.0.1599.69) 中,它以 UTF-8 的文件名到达服务器,效果很好。在 Firefox (24.0) 中,文件名在到达服务器时似乎已损坏。

我不相信 Firebug/Chrome 可能会告诉我有关编码的内容,因此我检查了请求数据包的十六进制。除了非 ASCII 字符在两个浏览器中的编码确实不同之外,其他一切都相同:

Chrome: C3 A9 (this is the expected UTF-8 for that character)
Firefox: EF BF BD (UTF-8 "replacement character"?!)

这是 Firefox 的错误吗?我尝试重命名文件,将 é 替换为 ó,而 Firefox 十六进制是相同的……所以这样的 mangle 看起来真的像浏览器错误。 (例如,如果 Firefox 混淆地发送 ISO-8859-1,但不接触它,我会看到一个 E9 字节,我可以在服务器端处理它,但它不应该破坏它!)

不管是什么原因,我可以在客户端或服务器端做些什么来纠正这个问题吗?如果一个替换字符确实被发送到服务器,那么它在那里似乎无法恢复,所以我几乎肯定需要在客户端这样做。

是的,存在此代码的页面有charset=utf-8,Firefox 在查看>字符编码下确认它认为该页面为 UTF-8。

此外,如果我将文件名转储到console.log,它看起来还不错——我猜它只是在setRequestHeader("X-File-Name",file.name) 中/之后受到破坏。

最后,似乎传递给 setRequestHeader() 的值应该能够具有高达 U+00FF 的代码点,因此 U+00E9 (é) 和 U+00F3 (ó) 应该不会造成问题,虽然更高的代码可能会触发 SyntaxError:http://www.w3.org/TR/XMLHttpRequest2/#the-setrequestheader-method

【问题讨论】:

  • 如果不知道 XHR 在您的情况下应该在哪里获取文件名,很难在这里说任何有用的东西。这是从哪里来的?
  • 删除时,e.dataTransfer.files ...我没有尝试硬编码文件名来消除该变量。
  • 我只是硬编码了文件名;相同的行为。 xhr.setRequestHeader("X-File-Name", "TEST-é-TEST.txt");
  • 我认为这确实缩小了问题所在:Firefox 的 setRequestHeader() 实现,当您传递一个包含非 ASCII 值的值时。如何克服?
  • 嗯。因此,查看 Firefox 中的 setRequestHeader,它正在按照规范中的说明进行操作:删除该 JSString 的每个 16 位单元的高字节并将低字节放入标头中。所以我不确定你为什么会在那里看到 EF BF BD。您应该看到的是 E9。您使用的是哪个 Firefox 版本?

标签: javascript google-chrome firefox utf-8 drag-and-drop


【解决方案1】:

非常感谢鲍里斯的帮助。以下是我通过我们在 cmets 中的交互发现的总结:

1) 核心问题是HTTP Request headers are supposed to be ISO-8859-1。之前版本的 Chrome 和 Firefox 都在 setRequestHeader() 调用中传递 UTF-8 字符串不变。这在 FF24.0 中发生了变化(显然 Chrome 也将很快发生变化),这样 FF 会丢弃高字节并仅传递每个字符的低字节。在我在问题中给出的示例中,这是可以恢复的,但是具有更高代码的字符可能会被不可挽回地损坏。

2) 一种解决方法是在客户端进行编码,例如:

setRequestHeader('X-File-Name',encodeURIComponent(filename))

然后在服务器端解码,例如在 PHP 中:

$filename=rawurldecode($_SERVER['HTTP_X_FILE_NAME'])

3) 请注意,这只是有问题的,因为我的 ajax 文件上传方法是在请求正文中发送原始文件数据,因此我需要通过自定义请求标头发送文件名(如在线许多教程中所示)。如果我改用FormData,我就不用担心这个了。我相信如果您想要可靠的、基于标准的 unicode 文件名支持,您应该使用 FormData 而不是请求标头方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2013-09-19
    • 1970-01-01
    • 2013-07-13
    • 2018-02-08
    • 2016-02-15
    • 2016-07-05
    相关资源
    最近更新 更多