javascript - 在 XHR 上传中处理非 ASCII 文件名

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

我有非常标准的 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 十六进制是相同的......所以这样的困惑看起来真的像是浏览器错误。 (如果 Firefox 混淆地发送 ISO-8859-1,例如,没有触及它,我会看到一个 E9 字节,我可以在服务器端处理它,但它不应该破坏它!)

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

是的,存在此代码的页面具有 charset=utf-8,并且 Firefox 在 View>Character Encoding 下确认它将该页面视为 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

最佳答案

非常感谢鲍里斯的帮助。以下是我通过评论中的互动发现的总结:

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 文件上传方法是在请求正文中发送原始文件数据,所以我需要通过自定义请求 header 发送文件名(如许多在线教程所示)。如果我使用 FormData相反,我不必担心这个。我相信如果您想要可靠的、基于标准的 unicode 文件名支持,您应该使用 FormData 而不是请求 header 方法。

关于javascript - 在 XHR 上传中处理非 ASCII 文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19253774/

相关文章:

javascript - 在获取 URL 之前了解 URL 的性质

javascript - 将 RegEx 从 JavaScript 转换为 Java

javascript - 你如何防止 JS 运动的水平干扰?

c# - 在 C# 中生成 JavaScript 和后续测试

css - Chrome 在 <picture> HTML5 中加载 2 张图片

在 Firefox 中使用无序列表时 CSS 列失败 (27)

html - href mailto 和 iOS safari

javascript - 在 JS 中获取 Android Chrome 浏览器地址栏高度

google-chrome - 哪个浏览器使用哪个HSTS预加载列表?

firefox - 纯文本文档的字符编码未声明 - mootool 脚本