Unique and temporary file names in PHP?

I need to convert some files to PDF and then attach them to email. I use Pear Mail for email, and it is fine (mostly - still developing some problems), but as part of this I need to create temporary files. Now I could use the tempnam () function, but it looks like it creates a file on the file system, which I don't want.

I just need to specify a name in the temporary file system (using sys_get_temp_dir () ), which will not conflict with someone, w370> of the same user calling the script more than once.

Suggestions?

+48
php
Jan 20 '09 at 4:55
source share
9 answers

I used uniqid () in the past to create a unique file name, but did not actually create the file.

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

The first parameter may be whatever you want, but I used rand () here to make it even more random. Using a dialing prefix, you can avoid collisions with other temp files on the system.

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

From there, you simply create a file. If all else fails, put it in a while loop and continue to generate it until you get the one that works.

 while (true) { $filename = uniqid('MyApp', true) . '.pdf'; if (!file_exists(sys_get_temp_dir() . $filename)) break; } 
+126
Jan 20 '09 at 5:04
source share
— -

Seriously, use tempnam (). Yes, this creates a file, but it is a very deliberate security measure designed to prevent another process on your system from “stealing” your file name and force your process to overwrite files that you do not need.

Ie, consider this sequence:

  • You generate a random name.
  • You check the file system to make sure that it does not exist. If so, repeat the previous step.
  • Another, evil process creates a file with the same name as the hard link to the file. Mr. Evil wants you to accidentally overwrite.
  • You open a file, thinking that you are creating a file, rather than opening an existing one in write mode, and start writing.
  • You just rewrote something important.

PHP tempnam () actually calls the mkstemp system under the hood (which for Linux ... will replace the "best practice" function for other operating systems), which goes through this process:

  • Choose a file name
  • Create a file with restrictive permissions inside the directory, which prevents other users from deleting files that it does not have (which makes the sticky bit in / var / tmp and / tmp)
  • Confirms that the generated file still has restrictive permissions.
  • If any of the above errors fail, try again with a different name.
  • Returns the generated file name.

Now you can do all these things yourself, but why, when the “right function” does everything that is required to create protected temporary files, and this almost always involves creating an empty file for you.

Exceptions:

  • You create a temporary file in a directory in which only your process can create / delete files.
  • Create a randomly created temporary directory that only your process can create / delete files.
+17
Feb 18 '16 at 21:17
source share

You can use the date and time part to create a unique file name, so it is not duplicated when called more than once.

+3
Jan 20 '09 at 5:48
source share

Consider using uuid for a file name. Consider the unicidal function. http://php.net/uniqid

+2
Jan 20 '09 at 5:04
source share

Another alternative based on @Lusid answer with maximum runtime fault tolerance:

 //////////// 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 } 



Note:

I prefer to use mt_rand instead of rand , because the first function uses the Mersenne Twister algorithm , and it is faster than the second ( LCG ).




Additional Information:

+2
Jan 11 '17 at 2:59
source share

Better if you use a unix timestamp with a user id.

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

0
Oct 29 '16 at 20:44
source share

My idea is to use a recursive function to see if the file name exists, and if so, go to the following integer:

 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); 
0
Aug 2 '17 at 10:30
source share

I recommend you use the PHP function http://www.php.net/tempnam

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

Or 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 ?> 
-one
Mar 10 2018-11-21T00:
source share
 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; } 
-one
Jan 08 '15 at 9:12
source share



All Articles