移除所有非字母数字字符以及单独的句点和斜线的正则表达式

4

我正在尝试为文件名列出白名单并防止路径操纵。我们接受从前端返回的文件名(我知道),并对其进行解析,以确定它是否在指定的文件夹中。因此,我们需要确保用户未传入可能会跳出指定文件夹的文件。这意味着我们认为有效文件名的情况如下:

  • 字母数字
  • 可以包含任一方向的单个斜杠
  • 可以包含单个点但不能是一对。

所以,“APP-TEST-file.20161115.1”是有效的,但“/../../ test // \”需要在检查文件系统之前删除一些字符。

这是我现在的正则表达式,不幸的是它移除了太多内容。

public static String validateFilePath(String fileName) {
    return fileName.replaceAll("[^A-Za-z0-9]+[(\\.\\/)\\+2]", "");
}

将 "APP-TEST-file.20161115.1" 转换为 "APP-TEST-file0161115.1"

非常感谢您的帮助。


+2 移除后,"/../../test//\" 变为 "test",但是 "APP-TEST-file.20161115.1" 保持不变。这是期望的输出吗? - secondbreakfast
请提供一些代表性的输入和期望的输出。 - Wiktor Stribiżew
有必要用一个正则表达式来完成这个任务吗?使用几个小的正则表达式会更容易编写和阅读。 - VGR
1
FYI:根据您的规则,APP-TEST-file.20161115.1是无效的,因为它包含连字符(-)。 - Andreas
1
@zero01alpha,这个方法很好,但它并没有涵盖我一些(未发布的边缘情况),这是我的错。如果我能给你虚拟的互联网积分,那就知道了。我已经决定采用更模块化的方法,就像Wasi Ahmad的答案一样。 - iamthereplicant
@Andreas 我刚刚意识到这一点,是因为我使用了错误的测试用例。那是针对另一段代码的。我会更新我的帖子。 - iamthereplicant
1个回答

2
你是否想要类似这样的内容呢?(我不太清楚你想要什么!)
String filename = "APP-TEST-file.20161115.1";
// replace two consecutive dots with a single dot
filename = filename.replaceAll("\\.+", ".");
// replace two consecutive forward slash with a single forward slash
filename = filename.replaceAll("/+", "/");
// replace two consecutive baskslash with a backslash
filename = filename.replaceAll("\\\\+", "\\\\");
// allow alphanumeric characters, dots and both type of slashes
filename = filename.replaceAll("[^A-Za-z0-9./\\\\]+", "");
System.out.println(filename);

它会打印出:
APPTESTfile.20161115.1

如果filename="/../../test//\\",那么它会输出 - /././test/\

我真是个傻瓜,一直以来都应该这样做。这就是我试图把一个大的正则表达式塞进去的结果。谢谢。 - iamthereplicant
根据“可以包含任何方向的单斜杠”规则,//\\不应该被折叠成/\吗?你的代码被折叠成了/\ - Andreas
@Andreas,据我所理解,OP想要将//折叠为/,将\折叠为\。这就是我写下这个的原因。无论如何,我不确定,正如你所看到的,我在我的帖子中写道 - “我不清楚你想要什么!” - Wasi Ahmad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接