Ars Informatica
September 28, 2020
Health Care Informatics
Web-based MySQL/PHP Databasing
Web Development
Favourite Software
Hardware for the Frugal Fanatic
Graphic Design and Image Processing
Free Scripts and Software
About Us
Contact Us

 Article Feed for this site

Creating unique file names for uploaded files using PHP

August 28, 2008

This simple bit of code checks for the presence of a file against one being uploaded, to prevent the original from being overwritten, by creating a new unique file name if required. The new file name uses the original file name as its base, but appends an underscore and then a unique integer.

For example, if file foo.pdf and foo_1.pdf already exist, then the new file will be saved as foo_2.pdf.

The code:

$file_suffix = substr($fn, (strrpos($fn, '.')+1));
if (file_exists($target_dir.$fn)) {
      if  (!preg_match('/_\d+.\w{3,4}$/', $fn))
            $fn = str_replace(".$file_suffix", "_1.$file_suffix", $fn);
      if (preg_match('/_(\d+).(\w{3,4})$/', $fn, $m))
            while (file_exists($target_dir.$fn))
                  $fn = str_replace("$m[1].$m[2]", ++$m[1].".$m[2]", $fn);

where $fn is a string containing the name of the uploaded file, and $target_dir the name of the target directory.

This code may look daunting, so some explanation follows for those who care.

First, we determine the file suffix - useful also for verifying file type. Function strrpos() finds the position of the final '.' character in the file name. The file suffix is the last part of file name string, i.e. that which starts with the first character after the position of this character. This is accomplished by

$file_suffix = substr($fn, (strrpos($fn, '.')+1));

Next, we see if the file is already present in the target directory, using if (file_exists($target_dir.$fn)).

Presuming that a file with that name already exists, we use Regular Expression matching to determine whether the uploaded file already has an underscore and digit preceding the file suffix, using

preg_match('/_\d+.\w{3,4}$/', $fn)

What this says, basically: check file name $fn to see if it ends with a string consisting of underscore, followed by one or more digits, followed by a period, followed by the three or four characters that make up a typical file suffix.

If no match is found, then we supply a tentative file name of this format, using
$fn = str_replace(".$file_suffix", "_1.$file_suffix", $fn). We could use preg_replace, but Regular Expression parsing is more processor intensive and thus slower than simple string matching.

At this point, the $fn file name will end with underscore and digit(s) and suffix. But we use preg_match anyways, to determine the actual number after the underscore, as well as the characters in the suffix -

preg_match('/_(\d+).(\w{3,4})$/', $fn, $m)

The parenthesized parts of the expression are returned in the match array $m. Thus, $m[1] returns the value of \d+, i.e. the one or more digits between the underscore and the period. $m[2] returns the value of \w{3,4}, or the three or four 'word' characters that make up the file name suffix.

The final part of the function - while(file_exists($target_dir.$fn)) checks for a file $fn in the target directory. If this exists, then we increment the number after the underscore by one using ++$m[1], and replace the number in the file name with the new one. And check again - while exits once a file name has been created that does not match one already present in the directory.

$fn now contains a new, unique file name derived from the original.


Copyright © 2020 Ars Informatica. All Rights Reserved.