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

cle*_*tus 54 php

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

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

建议?

Lus*_*sid 144

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

$filename = uniqid(rand(), true) . '.pdf';
Run Code Online (Sandbox Code Playgroud)

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

$filename = uniqid('MyApp', true) . '.pdf';
Run Code Online (Sandbox Code Playgroud)

从那里,您只需创建文件.如果所有其他方法都失败了,那就把它放在while循环中并继续生成它,直到你得到一个有效的循环.

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

  • 这个while循环应该真的写成do-while循环. (12认同)
  • 有点旧,但是在没有实现第二次故障转移中断的情况下,应该*永远不会被称赞.特别是代码可能是PHP CLI(或UI的其他"隐藏"部分)的一部分,我从来没有见过如此赞美一段非常糟糕的代码 - 没有留下深刻的印象 (5认同)
  • 我喜欢在uniquid上使用随机数作为第一个参数,但是我使用mt_rand()而不是因为它的速度.这对于使用while循环的地方以及有很多文件的地方都很有帮助. (4认同)
  • 你应该划分temp_dir和文件名:`!file_exists(sys_get_temp_dir().'/'.$ filename)` (3认同)

Chr*_*don 26

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

即,考虑这个顺序:

  • 您生成一个随机名称.
  • 您检查文件系统以确保它不存在.如果是,请重复上一步.
  • 另一个邪恶的进程创建一个文件,其名称与Evil先生希望您不小心覆盖的文件的硬链接相同.
  • 您打开文件,认为您正在创建文件而不是在写入模式下打开现有文件并开始写入文件.
  • 你只是覆盖了重要的东西.

PHP的tempnam()实际上调用了系统的mkstemp(用于Linux ...替换其他操作系统的"最佳实践"功能),这将通过以下过程:

  • 选择一个文件名
  • 在一个目录中创建具有限制权限的文件,该目录阻止其他人删除它不拥有的文件(这是粘性位在/ var/tmp和/ tmp上执行的操作)
  • 确认创建的文件仍具有限制性权限.
  • 如果上述任何一种失败,请使用其他名称重试.
  • 返回创建的文件名.

现在,您可以自己完成所有这些事情,但是为什么,当"正确的函数"执行创建安全临时文件所需的所有内容时,这几乎总是涉及为您创建一个空文件.

例外:

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