PHP中的唯一和临时文件名?

我需要将一些文件转换为PDF,然后将其附加到电子邮件。 我使用梨邮件的电子邮件的一面,这很好(主要 – 仍然在解决一些问题),但作为这一部分,我需要创build临时文件。 现在我可以使用tempnam()函数,但它听起来像在文件系统上创build一个文件,这不是我想要的。

我只想在临时文件系统中使用一个名称(使用sys_get_temp_dir() ),这个名字不会与运行同一用户的同一脚本的其他人不止一次地调用脚本冲突。

build议?

我过去使用uniqid()生成一个唯一的文件名,但实际上并没有创build文件。

$filename = uniqid(rand(), true) . '.pdf'; 

第一个参数可以是任何你想要的,但是我在这里使用了rand()使它更加随机。 使用设置的前缀,可以进一步避免与系统中其他临时文件的冲突。

 $filename = uniqid('MyApp', true) . '.pdf'; 

从那里,你只需创build文件。 如果一切都失败了,把它放在一个while循环,并继续生成,直到你得到一个工作。

 while (true) { $filename = uniqid('MyApp', true) . '.pdf'; if (!file_exists(sys_get_temp_dir() . $filename)) break; } 

真的,使用tempnam()。 是的,这会创build文件,但这是一个非常有意的安全措施,旨在防止系统上的另一个进程“窃取”您的文件名,并导致您的进程覆盖不需要的文件。

也就是说,考虑这个顺序:

  • 你生成一个随机的名字。
  • 您检查文件系统以确保它不存在。 如果是,请重复上一步。
  • 另一个邪恶的过程会创build一个与Evil希望你意外覆盖的文件具有相同名称的文件。
  • 您打开文件,认为您正在创build文件,而不是在写入模式下打开现有文件,然后开始写入文件。
  • 你只是重写了一些重要的东西。

PHP的tempnam()实际上调用了系统的mkstemp(这对于Linux来说……用其他操作系统的“最佳实践”函数代替),它经历了一个像这样的过程:

  • select一个文件名
  • 创build具有限制性权限的文件,在防止其他人删除它不拥有的文件的目录中(这是/ var / tmp和/ tmp上的粘性位)
  • 确认创build的文件仍然具有限制性的权限。
  • 如果上述任何一项失败,请用不同的名字再试一次。
  • 返回创build的文件名。

现在,你可以自己做所有这些事情,但是为什么当“正确的function”完成创build安全临时文件所需的一切时,几乎总是需要为你创build一个空文件。

例外:

  • 您正在目录中创build临时文件,只有您的进程可以创build/删除文件。
  • 创build一个随机生成的临时目录 ,只有你的进程可以创build/删除文件。

你可以使用部分date和时间来创build一个唯一的文件名,这样当多次调用时不会重复。

考虑使用uuid作为文件名。 考虑uniqid函数。 http://php.net/uniqid

基于@Lusid回答的另一个替代scheme是最大执行时间故障转移:

 //////////// Max exectution time of 10 seconds. $maxExecTime = time() + 10; $isUnique = false; while (time() !== $maxExecTime) { //////////// Unique file name $uniqueFileName = uniqid(mt_rand(), true) . '.pdf'; if (!file_exists(sys_get_temp_dir() . $uniqueFileName)){ $isUnique = true; break; } } if($isUnique){ //////////// Save your file with your unique name }else{ //////////// Time limit was exceeded without finding a unique name } 

注意:

我宁愿使用mt_rand而不是rand因为第一个函数使用Mersenne Twister algorithm ,而且比第二个函数( LCG )快。


更多信息:

如果您使用用户标识的unix时间戳,则更好。

$filename='file_'.time().'_'.$id.'.jepg';

我的想法是使用recursion函数来查看文件名是否存在,如果存在,则迭代到下一个整数:

 function check_revision($filename, $rev){ $new_filename = $filename."-".$rev.".csv"; if(file_exists($new_filename)){ $new_filename = check_revision($filename, $rev++); } return $new_filename; } $revision = 1; $filename = "whatever"; $filename = check_revision($filename, $revision); 

我build议你使用PHP函数http://www.php.net/tempnam

 $file=tempnam('tmpdownload', 'Ergebnis_'.date(Ymd).'_').'.pdf'; echo $file; /var/www/html/tmpdownload/Ergebnis_20071004_Xbn6PY.pdf 

http://www.php.net/tmpfile

 <?php $temp = tmpfile(); fwrite($temp, "writing to tempfile"); fseek($temp, 0); echo fread($temp, 1024); fclose($temp); // this removes the file ?> 
 function gen_filename($dir) { if (!@is_dir($dir)) { @mkdir($dir, 0777, true); } $filename = uniqid('MyApp.', true).".pdf"; if (@is_file($dir."/".$filename)) { return $this->gen_filename($dir); } return $filename; }