我们正在尝试比较相同的文件名,一个是由=运算符设置,另一个是通过上传后从Nodejs服务器获取文件返回的,如下面的代码块:
var name = "tên_đẹp.WAV";
// uploaded_file is the file (tên_đẹp) returned by calling an ajax function
// to get the uploaded file in uploaded_folder of a Nodejs server
ajaxUploadFile(name).done( function(e, uploaded_file) {
if(name == uploaded_file.name) {
return uploaded_file; // This line is never reached
else {
console.log(escape(name)); // t%EAn_%u0111%u1EB9p.WAV
console.log(escape(uploaded_file.name)); // te%u0302n_%u0111e%u0323p.WAV
}
}
正如您所看到的,2个转义命令的结果是不同的。 我不知道为什么他们使用不同的unicode格式,我怎么能让他们使用相同的Unicode字符集或任何解决方案将不胜感激? 谢谢。
答案 0 :(得分:3)
问题在于"e\u0302"
和"\u00EA"
在视觉上完全相同。一个是特定字符U+00EA(带有CIRCUMFLEX的LATIN SMALL LETTER E),另一个是带有组合字符U+0302的e
(组合CIRCUMFLEX ACCENT)。您必须首先将每个字符串规范化为标准形式以进行比较。
require('unorm');
var name = "tên_đẹp.WAV";
// uploaded_file is the file (tên_đẹp) returned by calling an ajax function
// to get the uploaded file in uploaded_folder of a Nodejs server
ajaxUploadFile(name).done( function(e, uploaded_file) {
if(name.normalize() == uploaded_file.name.normalize()) {
return uploaded_file; // This line is never reached
else {
console.log(escape(name)); // t%EAn_%u0111%u1EB9p.WAV
console.log(escape(uploaded_file.name)); // te%u0302n_%u0111e%u0323p.WAV
}
}
请注意,我已经加载了unorm
模块,该模块在字符串上调用的.normalize()
方法中进行了polyfill。此方法是ECMA6的一部分,在未来的Node版本中,您根本不需要加载unorm
。
不可能说出那里引入差异的原因,它可能是你的文本编辑器或浏览器。
答案 1 :(得分:1)
uploaded_file.name中的unicode字符是重音符号。 %u0302
是一个变音符号组合CIRCUMFLEX ACCENT,%u0323
是一个双重政治标记组合在下面。
另一方面,%EA
(ê)和%u1EB9
(ẹ)是集成了重音的等效字符。
这是由 Unicode等效处理的(参见维基百科)。 e%u0302
的序列被称为 canonicaly等效到%EA
,而另一对则类似。
要在node.js中正确处理比较,您必须将字符串规范化为规范形式(NFC或NFD)。这可以通过unorm:
来实现var unorm = require('unorm');
var s1 = 'êẹ';
var s2 = 'e\u0302e\u0323';
console.log(s1 == s2); // false
console.log(unorm.nfc(s1) == unorm.nfc(s2)); // true
console.log(unorm.nfd(s1) == unorm.nfd(s2)); // true
在这种情况下,NFC(组合)和NFD(分解)之间的选择无关紧要。
重要说明请注意,规范化有时会引入非显而易见的可利用漏洞,尤其是文件名漏洞,因为操作系统可能仍会将其视为不同。例如。看这个spotify的故事:Creative usernames and Spotify account hijacking。
答案 2 :(得分:1)
%EA
== ê
e%u0302
== e
+ ^
这两个unicode序列看起来相同,但输入方式不同。如果你需要比较它们,你必须先进行unicode规范化。