文件命名约定和不同操作系统之间允许的字符

时间:2011-11-28 16:48:31

标签: php file file-io fopen

我正在用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);
}

3 个答案:

答案 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)

不,你应该假设这很有可能失败。有两个原因:

  1. 如果2封电子邮件的文件名称相同(例如,selfie.jpg),该怎么办?
  2. 如果文件名包含不可接受的字符会怎么样?
  3. 您应该使用内部命名约定(例如user + datetime + sequential)并将名称保存在至少包含3个字段的MySQL表中:

    1. Id - 自动编号
    2. filename - 由php保存
    3. 原始名称 - 与原始电子邮件中一样
    4. 可选用户名 - 或发送电子邮件的用户代码或电子邮件地址
    5. 可选的日期时间戳
    6. 将原始文件名保存为VARCHAR,您将能够跟踪原始名称,甚至可以显示它,搜索它等等。

相关问题