34

How do I create a temporary file with a specified extension in php. I came across tempnam() but using it the extension can't be specified.

1

9 Answers 9

52

Easiest way i have found is to create tempfile and then just rename it. For example:

 $tmpfname = tempnam(sys_get_temp_dir(), "Pre_"); rename($tmpfname, $tmpfname .= '.pdf'); 
Sign up to request clarification or add additional context in comments.

3 Comments

Also rename returns true for success and false for failure so that is probably pretty useful as well.
As explained in @CrimsonNosedAnole answer, there is an edge case where tempnam() + extension might not be unique.
@DurandA I would be shocked if that edge case ever happens. Anyway rename would return false in that scenario, so you can just check.
15

my way is using 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 

3 Comments

Also, it would be quite useful to unlink ($file) not to create random trash in /tmp
I don't think this is safe. tempnam() ensures that $file doesn't exist. $file . '.extension' may as well exist.
As long as you use a sufficiently unique prefix and are consistent with its use it should be safe; unique-prefix-[tempnam-output].extension is only created after unique-prefix-[tempnam-output] is created and that file was guaranteed unique. You'll only get into trouble if you try deleting the tempnam file before you're done with your extended file.
10

This might simulate mkstemp() (see http://linux.die.net/man/3/mkstemp) a bit, achieving what you want to do:

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

So you could do:

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

Comments

5

Let's say tempnam() gives you a file of "filename". You move it to "filename.ext". At any point, tempnam() can give you "filename" again. If you check for "filename.ext", reject the filename given by tempnam(), and call it again, you still end up with the possibility that between one step and another, a file will get created with the same name. (This is discussed in the user comments on the documentation page for tempnam(): https://www.php.net/manual/en/function.tempnam.php.)

However, if you just leave the file created by tempnam() alone (not deleting "filename" until you delete "filename.ext") and work with that filename + the extension, then there is no chance that tempnam() will use that filename again (as far as I can see). Yes, it is messy to have "filename" and "filename.ext" for every single file. On the other hand, it solves the problem.

Comments

2

I prefer this solution:

$uid = uniqid('', true); $path = sys_get_temp_dir() . "some_prefix_$uid.myextension"; 

Note: I do not put the prefix in uniqid because, IMHO, it's not its duty

1 Comment

An extra / is required beween sys_get_temp_dir() and the filename (at least on my platform).
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; } 

Comments

0

The same as tempnam() except the additional parameter:

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

That 'p' at the end of the name stands for 'postfix'.

Comments

-1

Maybe using

move_uploaded_file($tmp_name, "$uploads_dir/$name.myextension");

See http://php.net/manual/en/function.move-uploaded-file.php#example-2209

Comments

-1

Rename does it, find the extension with pathinfo and then replace with the extension you want.

$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); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.