8

I am currently in the process of writing a mobile app with the help of phonegap. One of the few features that I would like this app to have is the ability to capture an image and upload it to a remote server...

I currently have the image capturing and uploading/emailing portion working fine with a compiled apk... but in my php, I am currently naming the images "image[insert random number from 10 to 20]... The problem here is that the numbers can be repeated and the images can be overwritten... I have read and thought about just using rand() and selecting a random number from 0 to getrandmax(), but i feel that I might have the same chance of a file overwriting... I need the image to be uploaded to the server with a unique name every-time, no matter what... so the php script would check to see what the server already has and write/upload the image with a unique name...

any ideas other than "rand()"?

I was also thinking about maybe naming each image... img + date + time + random 5 characters, which would include letters and numbers... so if an image were taken using the app at 4:37 am on March 20, 2013, the image would be named something like "img_03-20-13_4-37am_e4r29.jpg" when uploaded to the server... I think that might work... (unless theres a better way) but i am fairly new to php and wouldn't understand how to write something like that...

my php is as follows...

print_r($_FILES);
$new_image_name = "image".rand(10, 20).".jpg";
move_uploaded_file($_FILES["file"]["tmp_name"], "/home/virtual/domain.com/public_html/upload/".$new_image_name);

Any help is appreciated... Thanks in advance! Also, Please let me know if there is any further info I may be leaving out...

Jocelyn
  • 11,209
  • 10
  • 43
  • 60
JStormThaKid
  • 1,794
  • 3
  • 20
  • 26
  • `$new_image_name = "image".microtime().".jpg";` should suffice for your needs IF 2 images are not processed at exactly the same time (fraction of second). – Waygood Mar 20 '13 at 09:28

4 Answers4

18

You may want to consider the PHP's uniqid() function. This way the code you suggested would look like the following:

$new_image_name = 'image_' . date('Y-m-d-H-i-s') . '_' . uniqid() . '.jpg';
// do some checks to make sure the file you have is an image and if you can trust it
move_uploaded_file($_FILES["file"]["tmp_name"], "/home/virtual/domain.com/public_html/upload/".$new_image_name);

Also keep in mind that your server's random functions are not really random. Try random.org if you need something indeed random. Random random random.

UPD: In order to use random.org from within your code, you'll have to do some API requests to their servers. The documentation on that is available here: www.random.org/clients/http/.

The example of the call would be: random.org/integers/?num=1&min=1&max=1000000000&col=1&base=10&format=plain&rnd=new. Note that you can change the min, max and the other parameters, as described in the documentation.

In PHP you can do a GET request to a remote server using the file_get_contents() function, the cURL library, or even sockets. If you're using a shared hosting, the outgoing connections should be available and enabled for your account.

$random_int = file_get_contents('http://www.random.org/integers/?num=1&min=1&max=1000000000&col=1&base=10&format=plain&rnd=new');
var_dump($random_int);
ᴍᴇʜᴏᴠ
  • 4,804
  • 4
  • 44
  • 57
  • this seems to work really good, but how would I integrate random.org? I am definitely interested in true randomness – JStormThaKid Mar 20 '13 at 09:58
5

You should use tempnam() to generate a unique file name:

// $baseDirectory   Defines where the uploaded file will go to
// $prefix          The first part of your file name, e.g. "image"
$destinationFileName = tempnam($baseDirectory, $prefix);

The extension of your new file should be done after moving the uploaded file, i.e.:

// Assuming $_FILES['file']['error'] == 0 (no errors)
if (move_uploaded_file($_FILES['file']['tmp_name'], $destinationFileName)) {
    // use extension from uploaded file
    $fileExtension = '.' . pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
    // or fix the extension yourself
    // $fileExtension = ".jpg";
    rename($destinationFileName, $destinationFileName . $fileExtension);
} else {
    // tempnam() created a new file, but moving the uploaded file failed
    unlink($destinationFileName); // remove temporary file
}
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
1

Have you considered using md5_file ? That way all of your files will have unique name and you would not have to worry about duplicate names. But please note that this will return same string if the contents are the same.

Also here is another method:

do {
  $filename = DIR_UPLOAD_PATH . '/' . make_string(10) . '-' . make_string(10) . '-' . make_string(10) . '-' . make_string(10);
} while(is_file($filename));

return $filename;

/**
* Make random string
*
* @param integer $length
* @param string $allowed_chars
* @return string
*/
function make_string($length = 10, $allowed_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890') {
  $allowed_chars_len = strlen($allowed_chars);

  if($allowed_chars_len == 1) {
    return str_pad('', $length, $allowed_chars);
  } else {
    $result = '';

    while(strlen($result) < $length) {
      $result .= substr($allowed_chars, rand(0, $allowed_chars_len), 1);
    } // while

    return $result;
  } // if
} // make_string
Goran
  • 3,292
  • 2
  • 29
  • 32
  • what if they are called the same? md5_file('image.jpg')===md5_file('image.jpg') – Waygood Mar 20 '13 at 09:25
  • or maybe i get rid of "image" all together? do something like print_r($_FILES); $new_image_name = md5().".jpg"; move_uploaded_file($_FILES["file"]["tmp_name"], "/home/virtual/domain.com/public_html/upload/".$new_image_name); – JStormThaKid Mar 20 '13 at 09:28
  • Waygood you are clearly not familiar with md5_file since you gave comment like that. It returns the hash of the content, not the filename. Filename has nothing to do with it. Please test it and you will see that two files with same name but different content will return different hashes. P.S. Please remove the negative vote after you successfully test :) – Goran Mar 20 '13 at 09:31
  • Let me show you what md5_file does: md5(file_get_contents("1.php")) === md5_file("1.php") – Goran Mar 20 '13 at 09:33
  • D'oh! was thinking of md5. Anyway what if they are the same "contents", one will overwrite the other. Then if you want to delete one, you delete both! – Waygood Mar 20 '13 at 09:33
  • Well then this is not in the spirit of "no duplicate files" thinking and lets users use more space but whatever... Guess you are right – Goran Mar 20 '13 at 09:39
  • I have edited my answer according to your suggestions and provided the new one that resolves the issue you were suggesting. Could you please remove the negative vote? Thank you :) – Goran Mar 20 '13 at 09:51
-1

Function will create a unique name before uploading image.

// Upload file with unique name
if ( ! function_exists('getUniqueFilename'))
{
    function getUniqueFilename($file)
    {
        if(is_array($file) and $file['name'] != '')
        {
            // getting file extension
            $fnarr          = explode(".", $file['name']);
            $file_extension = strtolower($fnarr[count($fnarr)-1]);

            // getting unique file name
            $file_name = substr(md5($file['name'].time()), 5, 15).".".$file_extension;
            return $file_name;

        } // ends for is_array check
        else
        {
            return '';

        } // else ends

    } // ends
}
Ayaz Shah
  • 435
  • 1
  • 5
  • 24