nodejs比较Unicode文件名

时间:2014-01-18 18:26:24

标签: javascript node.js unicode

我们正在尝试比较相同的文件名,一个是由=运算符设置,另一个是通过上传后从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字符集或任何解决方案将不胜感激? 谢谢。

3 个答案:

答案 0 :(得分:3)

问题在于"e\u0302""\u00EA"在视觉上完全相同。一个是特定字符U+00EA(带有CIRCUMFLEX的LATIN SMALL LETTER E),另一个是带有组合字符U+0302e(组合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规范化。