edwinNosh
edwinNosh

Reputation: 399

Create Unique Image Names

What's a good way to create a unique name for an image that my user is uploading?

I don't want to have any duplicates so something like MD5($filename) isn't suitable.

Any ideas?

Upvotes: 6

Views: 20577

Answers (15)

zsubzwary
zsubzwary

Reputation: 1246

You should try to meet two goals: Uniqueness, and usefulness.

Using a GUID guarantees uniqueness, but one day the files may become detached from their original source, and then you will be in trouble.

My typical solution is to embed crucial information into the filename, such as the userID (if it belongs to a user) or the date and time uploaded (if this is significant), or the filename used when uploading it.

This may really save your skin one day, when the information embedded in the filename allows you to, for example, recover from a bug, or the accidental deletion of records. If all you have is GUIDs, and you lose the catalogue, you will have a heck of a job cleaning that up.

For example, if a file "My Holiday: Florida 23.jpg" is uploaded, by userID 98765, on 2013/04/04 at 12:51:23 I would name it something like this, adding a random string ad8a7dsf9:

20130404125123-ad8a7dsf9-98765-my-holiday-florida-23.jpg

Uniqueness is ensured by the date and time, and random string (provided it is properly random from /dev/urandom or CryptGenRandom. If the file is ever detached, you can identify the user, the date and time, and the title. Everything is folded to lower case and anything non-alphanumeric is removed and replaced by dashes, which makes the filename easy to handle using simple tools (e.g. no spaces which can confuse badly written scripts, no colons or other characters which are forbidden on some filesystems, and so on).

Upvotes: 0

nafischonchol
nafischonchol

Reputation: 88

I think it would be good for you.

<?php
    $name=uniqid(mt_rand()).$image_name;
 ?>

Upvotes: 0

Pingui
Pingui

Reputation: 1496

Ready-to-use code:

$file_ext = substr($file['name'], -4); // e.g.'.jpg', '.gif', '.png', 'jpeg' (note the missing leading point in 'jpeg')
$new_name = sha1($file['name'] . uniqid('',true)); // this will generate a 40-character-long random name
$new_name .= ((substr($file_ext, 0, 1) != '.') ? ".{$file_ext}" : $file_ext); //the original extension is appended (accounting for the point, see comment above)

Upvotes: -2

andy
andy

Reputation: 106

Grab the file extension from uploaded file:

$ext = pathinfo($uploaded_filename, PATHINFO_EXTENSION);

Grab the time to the second: time()

Grab some randomness: md5(microtime())

Convert time to base 36: base_convert (time(), 10, 36) - base 36 compresses a 10 byte string down to about 6 bytes to allow for more of the random string to be used

Send the whole lot out as a 16 char string:

$unique_id = substr( base_convert( time(), 10, 36 ) . md5( microtime() ), 0, 16 ) . $ext;

I doubt that will ever collide - you could even not truncate it if you don't mind very long file names.

Upvotes: 8

user1486707
user1486707

Reputation: 161

as it was mentioned, i think that best way to create unique file name is to simply add time(). that would be like

$image_name = time()."_".$image_name;

Upvotes: 16

Simon
Simon

Reputation: 1869

Something like this could work for you:

while (file_exists('/uploads/' . $filename . '.jpeg')) {
   $filename .= rand(10, 99);
}

Upvotes: -1

Koraktor
Koraktor

Reputation: 42903

I'd recommend sha1_file() over md5_file(). It's less prone to collisions. You could also use hash_file('sha256', $filePath) to get even better results.

Upvotes: 1

sv_in
sv_in

Reputation: 14039

try this file format:

$filename = microtime(true) . $username . '.jpg';

Upvotes: 0

Dmytro Evseev
Dmytro Evseev

Reputation: 11581

For good performance and uniqueness you can use approach like this:

  • files will be stored on a server with names like md5_file($file).jpg

  • the directory to store file in define from md5 file name, by stripping first two chars (first level), and second two (second level) like that:

    uploaded_files\ 30 \ c5 \ 30 c5 67139b64ee14c80cc5f5006d8081.pdf

  • create record in database with file_id, original file name, uploaded user id, and path to file on server

  • on server side create script that'll get role of download providing - it'll get file by id from db, and output its content with original filename provided by user (see php example of codeigniter download_helper ). So url to file will look like that:

    http://site.com/download.php?file=id


Pros:

  • minified collisions threat

  • good performance at file lookup (not much files in 1 directory, not much directories at the same level)

  • original file names are saved

  • you can adjust access to files by server side script (check session or cookies)

Cons:

  • Good for small filesizes, because before user can download file, server have to read this file in memory

Upvotes: 0

DhruvPathak
DhruvPathak

Reputation: 43235

How big is the probablity of two users uploading image with same name on same microsecond ?

try

    $currTime = microtime(true);
    $finalFileName = cleanTheInput($fileName)."_".$currTime;

// you can also append a _.rand(0,1000) in the end to have more foolproof name collision

    function cleanTheInput($input)
    {
     // do some formatting here ...
    }

This would also help you in tracking the upload time of the file for analysis. or may be sort the files,manage the files.

Upvotes: 0

Matt Gibson
Matt Gibson

Reputation: 38238

If you actually need a filename (it's not entirely clear from your question) I would use tempnam(), which:

Creates a file with a unique filename, with access permission set to 0600, in the specified directory.

...and let PHP do the heavy lifting of working out uniqueness. Note that as well as returning the filename, tempnam() actually creates the file; you can just overwrite it when you drop the image file there.

Upvotes: 4

Matthew
Matthew

Reputation: 48284

You could take a hash (e.g., md5, sha) of the image data itself. That would help identify duplicate images too (if it was byte-for-byte, the same). But any sufficiently long string of random characters would work.

You can always rig it up in a way that the file name looks like:

/image/0/1/012345678/original-name.jpg

That way the file name looks normal, but it's still unique.

Upvotes: 2

Lawrence Cherone
Lawrence Cherone

Reputation: 46602

lol there are around 63340000000000000000000000000000000000000000000000 possibility's that md5 can produce plus you could use just tobe on the safe side

$newfilename = md5(time().'image');
if(file_exists('./images/'.$newfilename)){
    $newfilename = md5(time().$newfilename);
}
//uploadimage

Upvotes: 0

Oliver A.
Oliver A.

Reputation: 2900

For short names:

$i = 0;
while(file_exists($name . '_' . $i)){
  $i++;
}

WARNING: this might fail on a multi threaded server if two user upload a image with the same name at the same time. In that case you should include the md5 of the username.

Upvotes: 0

Ptival
Ptival

Reputation: 9437

http://php.net/manual/en/function.uniqid.php maybe?

  • You can prefix it with the user id to avoid collisions between 2 users (in less than one millisecond).

Upvotes: 0

Related Questions