使用php创建一个特定扩展名的临时文件

29

我如何在php中创建指定扩展名的临时文件。 我找到了tempnam(),但使用它无法指定扩展名。


3
不可以在 tempname() 中指定扩展名,你需要自己创建一个自定义函数来实现这个功能,可以参考 http://theserverpages.com/php/manual/en/function.tempnam.php 的 User Contributed Notes - Cyclonecode
9个回答

46

我发现最简单的方法是创建临时文件,然后将其重命名。例如:

 $tmpfname = tempnam(sys_get_temp_dir(), "Pre_");
 rename($tmpfname, $tmpfname .= '.pdf');

2
同时,将返回值true重命名为成功,false重命名为失败,这也非常有用。 - nathan hayfield
正如@CrimsonNosedAnole的回答所解释的那样,tempnam()和扩展名结合可能存在一种边缘情况,导致不唯一。 - DurandA
@DurandA 如果那种边缘情况真的发生了,我会感到震惊的。无论如何,在这种情况下,重命名将返回false,因此您可以进行检查。 - nathan hayfield

15

我的方法是使用tempnam

$file = tempnam(sys_get_temp_dir(), 'prefix');
file_put_contents($file.'.extension', $data);
{
   //use your file
}
unlink($file);//to delete an empty file that tempnam creates
unlink($file.'.extension');//to delete your file

此外,调用 unlink($file) 可以避免在 /tmp 目录下产生随机垃圾文件,这非常有用。 - Dmitry Ginzburg
17
我认为这不安全。tempnam() 确保 $file 不存在,但是 $file . '.extension' 可能已经存在。 - hytromo
1
只要您使用足够独特的前缀并且在使用时保持一致,就应该是安全的;unique-prefix-[tempnam-output].extension仅在创建了unique-prefix-[tempnam-output]并且该文件已经被保证为唯一后才会被创建。如果您在完成扩展文件之前尝试删除tempnam文件,则可能会遇到麻烦。 - rymo

9
这可能会模拟mkstemp()(参见http://linux.die.net/man/3/mkstemp),从而实现您想要做的事情:
function mkstemp( $template ) {
  $attempts = 238328; // 62 x 62 x 62
  $letters  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  $length   = strlen($letters) - 1;

  if( mb_strlen($template) < 6 || !strstr($template, 'XXXXXX') )
    return FALSE;

  for( $count = 0; $count < $attempts; ++$count) {
    $random = "";

    for($p = 0; $p < 6; $p++) {
      $random .= $letters[mt_rand(0, $length)];
    }

    $randomFile = str_replace("XXXXXX", $random, $template);

    if( !($fd = @fopen($randomFile, "x+")) )
      continue;

    return $fd;
  }

  return FALSE;
}

那么你可以这样做:

if( ($f = mkstemp("test-XXXXXX.txt")) ) {
  fwrite($f, "test\n");
  fclose($f);
}

5
假设tempnam()给你一个名为"filename"的文件。你将它移动到"filename.ext"。在任何时候,tempnam()都可以再次给出"filename"。如果你检查"filename.ext",拒绝tempnam()给出的文件名,并再次调用它,你仍然有可能在一步和另一步之间创建具有相同名称的文件。(这在tempnam()的文档页面的用户注释中讨论:https://www.php.net/manual/en/function.tempnam.php.
然而,如果你只是让tempnam()创建的文件保持不变(在删除"filename"之前不删除它,直到你删除了"filename.ext"),并且使用该文件名+扩展名进行操作,则我认为tempnam()不会再次使用该文件名。(是的,对于每个文件都有"filename"和"filename.ext"是很混乱的。另一方面,它解决了问题。)

1
我更喜欢这个解决方案:
$uid = uniqid('', true);
$path = sys_get_temp_dir() . "some_prefix_$uid.myextension";

注意:我没有在uniqid中加入前缀,因为在我看来,这不是它的职责。

在我的平台上,sys_get_temp_dir()和文件名之间需要多加一个/ - DurandA

1
public static function makeTempFileInFolder($prefix, $suffix, $folder="")
{
  if (strlen($folder)==0) $folder = sys_get_temp_dir();
  do { 
    $file = $folder."/".$prefix.rand(1,99999).time().$suffix; 
  } while (file_exists($file));
  return $file;
}

0

tempnam()相同,除了额外的参数:

function tempnamp($dir, $prefix, $postfix) {
  $maxAttempts = 1000;
  // Trim trailing slashes from $dir.
  $dir = rtrim($dir, DIRECTORY_SEPARATOR);
  // If we don't have permission to create a directory, fail, otherwise we will
  // be stuck in an endless loop.
  if (!is_dir($dir) || !is_writable($dir)) return false;
  // Make sure characters in prefix and postfix are safe.
  if (strpbrk($prefix, '\\/:*?"<>|') !== false) return false;
  if (strpbrk($postfix, '\\/:*?"<>|') !== false) return false;
  // Attempt to create a random file until it works.
  $attempts = 0;
  do
  {
    $path = $dir.DIRECTORY_SEPARATOR.$prefix.mt_rand(100000, mt_getrandmax()).$postfix;
    $fp = @fopen($path, 'x+');
  } while (!$fp && $attempts++ < $maxAttempts);
  if ($fp) fclose($fp);
  return $path;
}

名称末尾的“p”代表“后缀”。


-1

-1

使用Rename函数,使用pathinfo查找文件扩展名,然后替换为所需的扩展名。

$tmpfname = tempnam(sys_get_temp_dir(), 'FOO');
$newname = str_replace(pathinfo($tmpfname, PATHINFO_EXTENSION),'pdf',$tmpfname);
rename($tmpfname, $newname);
//do what you want with $newname
unlink($newname);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接