我正在寻找一个PHP函数来将字符串清理成安全有效的文件名而没有目录分隔符(斜杠)。
理想情况下,它应该是可逆的,并且不应该超过必要的名称。
当然我想防止故意的目录遍历攻击。但我也想防止创建子文件夹。
我认为urlencode()
会起作用,但我想知道这是否足够,和/或是否有更好或更受欢迎的东西。
此外,如果在Windows上有一些同样有效的东西(反斜杠作为目录分隔符) - 所以解决方案是可移植的。
用例/情景:
作为数据导入的一部分,我想将远程URL中的文件下载到本地文件系统中。网址来自csv文件。大多数都没问题,但它们可能包含比预期更多的斜杠。
E.g。大多数都是这样的:
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
。
答案 0 :(得分:2)
您可以创建一组替换。例如,您可以使文件名中出现的/ char用其他类似的东西来表示,例如"(斜杠)"。只需使用str_replace在查找文件名和将文件名编码为url之间切换。这只是一个例子。
答案 1 :(得分: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|
你明白了。
答案 2 :(得分: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;
}