我有以下情况:

在我的Reaction应用程序上,我有这个正则表达式来验证文件名:

const validCharsRegex = /^([\w\s()+[żźćńółęąśŻŹĆĄŚĘŁÓŃ-]+)(\.[A-Za-z0-9]+)?$/;

if (!validCharsRegex.test(file.name)) {
    errorLabels.push(translate(labels.forbiddenCharacters));
}

我想允许在文件名中使用波兰字符.

该问题仅出现在Mac OS X系统(如różowożółty.pdf)上的文件名上.我有一些开放的组件RC-Upload,它接受文件名并进一步处理它.

Windows上,所有像różowo-żółty.pdf这样的文件名都是匹配的,所以没问题.但与Mac OS X笔记本电脑上创建的同名文件不匹配.我怎么才能解决这个问题呢?可能是用编码?

推荐答案

这是因为accented chars are stored differently on Mac OS X and Windows.

Windows使用UTF-16作为文件名,因此大多数码点都进行了编码 在2个字节中.在基本多语言平面之外,它们被编码为 "代理项对",它将占用4个字节.这意味着您可以 我有一个像écosse.pdf这样的文件,其中é可以存储在一个 单码点或在两个码点中,其中将跟随e 由Unicode的尖锐口音´.这意味着您的文件夹可以 将名为écosse.pdf的文件存储两次(一次存储é,一次存储 e+´),这可能非常令人困惑!

Mac OS X上,他们使用UTF-8,但使用Unicode NFD (N正规化F正则D分解). 这意味着é将始终与2个码点一起存储: e+´.这避免了多个文件具有相同的名称.

JavaScript中,可以使用 .normalize()种方法:

const filenames = [
  'ecosse.pdf', // No accent at all
  'écosse.pdf', // 1 codepoint to store "é"
  'écosse.pdf'  // 2 codepoints to store "é" = "e" + "´"
];

filenames.forEach(filename => {
  // You can separate the letter and the accent codepoints with
  // the help of .normalize('NFD');
  const nfdFilename = filename.normalize('NFD');
  console.log({
    original: {
      string: filename,
      length: filename.length
    },
    NFD: {
      string: nfdFilename,
      length: nfdFilename.length
    }
  });
});

为了验证您的模式,您必须在以下两种模式之间进行 Select NFD或NFC.此示例解释了您的问题:

const filenames = [
  'różowo-żółty.pdf', // NFC (Most probably Windows)
  'różowo-żółty.pdf', // NFD (Mac OS X)
  'różowo-żółty.pdf', // mix of NFC and NFD (possible on Windows but not Mac OS X).
];

filenames.forEach(filename => {
  const nfdFilename = filename.normalize('NFD');
  const nfcFilename = filename.normalize('NFC');
  console.log({
    original: {
      string: filename,
      length: filename.length
    },
    NFD: {
      string: nfdFilename,
      length: nfdFilename.length
    },
    NFC: {
      string: nfcFilename,
      length: nfcFilename.length
    }
  });
});

顺便说一句,对于JavaScript,您可以使用u模式修饰符 或v模式修饰符,以启用Unicode处理.这将 为您提供使用\p{L}来匹配任何 语言.对于\p{Latin},您可以更具体,但这可能 仍然不完全是你想要的,就像波兰人看起来的那样 另一个角色类.但if you convert the string to NFC then you can use your pattern%:

const regexFilename = /^([\w\s()+[żźćńółęąśŻŹĆĄŚĘŁÓŃ-]+)(\.[A-Za-z0-9]+)?$/;

const filenames = [
  'różowo-żółty.pdf', // NFC (Most probably Windows)
  'różowo-żółty.pdf', // NFD (Mac OS X)
  'różowo-żółty.pdf', // mix of NFC and NFD (possible on Windows but not Mac OS X).
];

filenames.forEach(filename => {
  console.log({
    filename: filename,
    match: filename.normalize('NFC').match(regexFilename)
  });
});

Reactjs相关问答推荐

React onKeyUp不一致地使用快速Shift+键按压

URL参数和React路由中的点

Next.js-图像组件加载问题

根据另一个Select中的选定值更改Select中的值

我如何在不被 destruct 的情况下将导航栏固定在顶部?

如何在物料界面react 的多选菜单中设置最大 Select 数限制

在任何渲染之前在ReactJs中获取数据

useEffect firebase 清理功能如何工作?

在reactjs中刷新页面时丢失状态值

React Native - 如何处理错误带有有效负载的NAVIGATE操作..未被任何导航器处理?

如何在 React 过滤器中包含价格过滤器逻辑?

如何在 React.js 中提取 PDF 的内容?

使用状态与复选框不同步

当每个元素都可拖动时,移动设备上的滚动列表出现问题

React Native Realm 应用程序在发布构建后崩溃

DatePicker MUI 如何在日历左侧显示清除文本

在 Formik 表单中访问子组件的值

如何不旋转 mui 自动完成弹出图标?

设置 Material UI 表格默认排序

链接的音译 Gatsby JS