我正在用PHP编写一段代码来保存电子邮件附件。 我可以假设这绝不会失败,因为OS之间允许的字符不同吗?
foreach($message->attachments as $a)
{
// Make dir if not exists
$dir = __DIR__ . "/saved/$uid"; // Message id
if (!file_exists($dir)) mkdir($dir) or die("Cannot create: $dir");
// Save the attachment using original!!! filename as found in email
$fp = fopen($dir . '/' . $a->filename, 'w+');
fwrite($fp, $a->data);
fclose($fp);
}
答案 0 :(得分:2)
您永远不应该使用您无法控制的名称,它可以包含各种字符,例如../../..
。
您可以使用basename
之类的函数进行清理,并使用DIRECTORY_SEPARATOR
这样的常量来分隔目录。
我个人会重命名该文件,但您也可以在使用之前过滤变量。
答案 1 :(得分:0)
最好替换窗口上文件名中可能出现的某些字符。
Unix几乎可以处理文件名中的任何字符(但不能处理“/”和0x00 [null字符]),但为了防止编码问题和下载文件的困难,我建议更换任何不匹配的内容
/[A-Za-Z0-9_-\.]/g
,它满足POSIX完全可移植的文件名格式。
所以preg_replace("/[^A-Za-Z0-9_-\.]/g","_",$filename);
会做得很好。
更慷慨的方法是仅替换|\?*<":>+[]\x00/
,这样可以保留特殊语言字符,例如öäü不变,并且与FAT32,NTFS,任何Unix和Mac OS X兼容。
在这种情况下使用preg_replace("/[\|\\\?\*<\":>\+\[\]\/]\x00/g","_",$filename);
答案 2 :(得分:0)
不,你应该假设这很有可能失败。有两个原因:
您应该使用内部命名约定(例如user + datetime + sequential)并将名称保存在至少包含3个字段的MySQL表中:
将原始文件名保存为VARCHAR,您将能够跟踪原始名称,甚至可以显示它,搜索它等等。