0

我正在寻找一个 PHP 函数来将字符串清理为没有目录分隔符(斜杠)的安全有效的文件名。

理想情况下,它应该是可逆的,并且不应过度扰乱名称。

当然我想防止故意的目录遍历攻击。但我也想防止创建子文件夹。

我认为这urlencode()可行,但我想知道这是否足够,和/或是否有更好或更受欢迎的东西。

此外,如果有一些东西在 Windows 上同样有效(反斜杠作为目录分隔符) - 那么该解决方案将是可移植的。

用例/场景:

作为数据导入的一部分,我想将文件从远程 url 下载到本地文件系统中。网址来自 csv 文件。它们中的大多数都可以,但它们可能包含比预期更多的斜线。

例如,它们中的大多数是这样的:
https://files.example.com/pdf/12345.pdf

但随后个别文件可能是这样的:
https://files.example.com/pdf/1/2345.pdf

这些文件都应该进入同一个目录,例如 https://files.example.com/pdf/12345.pdf->/destination/dir/12345.pdf

类似的文件1/2345.pdf不应导致子目录。相反,/应该以某种(可逆)方式转义。例如,使用 urlencode() 这将是1%2F2345.pdf.

4

3 回答 3

2

这应该可以帮助你。

输入https ://files.example.com/pdf/1/2345.pdf

输出:pdf_1_2345.pdf

$url = 'https://files.example.com/pdf/1/2345.pdf';
$parse = parse_url($url);

//get path, remove first slash
//$path: pdf/1/2345.pdf
$path = substr($parse['path'],1);

//result becomes: pdf_1_2345.pdf
$result = str_replace('/','_',$path);

编辑:最好的办法是将远程文件 url 存储在数据库中,散列其值(使用 md5 或类似名称)并在本地以该名称保存文件,将该散列值也存储在数据库中。

这是您最好的选择,这样您就可以始终知道哪个远程文件对应于您的本地文件,反之亦然,并且您不必在本地处理文件名,因为它们可以是您想要的任何文件名(只要您保留他们检查唯一性)

Database Table:
--------------------
| id | remote_url                  | local_name     |
-----------------------------------------------------
| 1  | http://example/.../123.pdf  | sdflkfd..dl.pdf|

你明白了。

于 2016-02-28T21:57:28.090 回答
2

您可以创建一组替换。例如,您可以使出现在文件名中的 / 字符用“(斜杠)”之类的其他内容表示。只需使用 str_replace 在查找文件名和将文件名编码为 url 之间切换。这只是一个例子。

于 2016-02-28T21:47:41.733 回答
0

您可以使用此功能,它将所有目录分隔符替换为下划线。

function secureFilePath($str)
{
    $str = str_replace('/', '_', $str);
    $str = str_replace('\\', '_', $str);
    $str = str_replace(DIRECTORY_SEPARATOR, '_', $str); // In case it does not equal the standard values
    return $str;
}
于 2017-09-07T13:30:51.783 回答