Generating a time-based unique file name for uploads without creating a race condition

StackOverflow https://stackoverflow.com/questions/1261805

  •  12-09-2019
  •  | 
  •  

Question

I'm generating a unique filename for uploaded files with the following code

$date = date( 'U' );
$user = $_SERVER[REMOTE_ADDR];
$filename = md5($date.$user);

The problem is that I want to use this filename again later on in the script, but if the script takes a second to run, I'm going to get a different filename the second time I try to use this variable.

For instance, I'm using an upload/resize/save image upload script. The first operation of the script is to copy and save the resized image, which I use a date function to assign a unique name to. Then the script processses the save and saves the whole upload, and assigns it a name. At the end of the script ($thumb and $full are the variables), I need to insert into a MySQL database, the filenames I used when i saved the uploads.

Problem is, sometimes on large images it takes more than a second (or during the process, the seconds change) resulting in a different filename being put into the database than is what the file is actually saved under.

Is this just not a good idea to use this method of naming?

Was it helpful?

Solution

AFAIK it's a great way to name the files, although I would check file_exists() and maybe tack on a random number.

You need to store that filename in a variable and reference it again later, instead of relying on the algorithm each time. This could be stored in the user $_SESSION, a cookie, a GET variable, etc between pageloads.

Hope that helps

OTHER TIPS

Just want add that php has a function to create identifiers: uniqid. You can also prefix the identifier with a string (date maybe?).

Always validate your user's input, and the server headers!

I would recommend storing the file name in the session (as per AI). If you store it in one of the other variables, it is more likely for the end user to be able to attack the system through it. MD5 of user concatenated with rand() would be a nice way to get a long list of unique values. Just using rand() would probably have a higher percentage of conflicts.

I am not sure about the process that you are following for uploading files, but another way to handle file uploads is with PHP's built in handlers. You can upload the file and then use the "secure" methods for pulling uploaded files out of the temporary space. (the temporary space in this instance can be safely located outside of the open base dir directive to prevent tampering). is_uploaded_file() and move_uploaded_file() from: http://php.net/manual/en/features.file-upload.post-method.php example 2 might handle the problem you are encountering.

Definitely check for an existing file in that location if you are choosing a filename on the fly. If user input is allowed in any way shape or form, validate and filter the argument to make sure it is safe. Also, if the storage folder is web accessible, make sure you munge the name and probably the extension as well. You do not want someone to be able to upload code and then be able to execute it. That officially leads to BAD activities.

I just discovered that PHP has a built-in function for this, called tempnam. It even avoids race conditions. See http://php.net/manual/en/function.tempnam.php.

Why not to use

$filename = md5(rand());

This will be pretty much unique in every case. And if you find that $filename already exists you can just call it again.

Not a good idea using ID dependent on time – if you upload two images at the same time, the later one can overwrite the earlier. You should look at function such as uniqid(). However, if this upload/resize/save script is meant to be "single-user", then this is not such a big problem.

To the problem itself. If I were you, I would just save the computed filename to some variable a use the variable from that point. Computing already computed is waste of time. And when uploading some really big images, or more images at once, script can take even 20 seconds. You cannot depend on fact that you'll make everything you want in one second.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top