1

So I am trying to upload some images to a folder on my server with the script below,but it saves every image as "image.jpg" and it overwrites the last uploaded image if I try to upload multiple ones.As you can see I commented the part that checks if the file already exists to let me upload a file and overwrite the latest one.Help!I need something modified to just randomize the name or get the original image name.

<?php
$target_dir = "wp/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);

// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
    $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
    if($check !== false) {
        echo "File is an image - " . $check["mime"] . ".";
        $uploadOk = 1;
    } else {
        echo "File is not an image.";
        $uploadOk = 0;
    }
}
// Check if file already exists
/*if (file_exists($target_file)) {
    echo "Sorry, file already exists.";
    $uploadOk = 0;
}*/
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
    echo "Sorry, your file is too large.";
    $uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "png" && $imageFileType != "jpg") {
    echo "Sorry, only PNG and JPG files are allowed.";
    $uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
    echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
        echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
    } else {
        echo "Sorry, there was an error uploading your file.";
    }
}
?>
Patr0nu
  • 33
  • 1
  • 4
  • The problem is `$target_file` this gets filled with $_FILES["fileToUpload"]["name"]. Try var_dump(`$_FILES["fileToUpload"]["name"]). The files are sent as file array. This will let you know that the names are stored in an array. Should point you in the direction of the solution. – Mouser Jan 11 '15 at 14:53
  • To randomize the name of your uploads you can append to the name the current date in milliseconds with time(), so that every next update with the same name won't collide and the upload would work without overwriting the existing file. – Masiorama Jan 11 '15 at 15:00

2 Answers2

1

A simple way to get a unique filename is to get the current Unix time in milliseconds and append (or prepend) that to the filename. The command to use is microtime().

For example:

$target_file = $target_dir . microtime() . basename($_FILES["fileToUpload"]["name"]);

You could also try things like hashing the file to get a unique hash with low probability of collisions, but this is faster and just as effective.

Aaron D
  • 7,540
  • 3
  • 44
  • 48
  • what if two request comes from two client with same file name at the same time? – partho Feb 27 '17 at 04:42
  • Collisions are a (slim) possibility. Another idea to explore is using some kind of using PHP's [UUID generation function](http://php.net/manual/en/function.uniqid.php) with `more_entropy` enabled to reduce the chance of collisions (please note that that function still relies on `microtime` for the generation of the UUID). – Aaron D Mar 21 '17 at 11:41
1

You can implement something like Windows's auto-file-renaming:

$try = 1;
while($file_exists($target_file)) {
    $target_file = preg_replace('/(\(\\d+\))*(\.[^\\(\\)]+)$/',
        "({$try})\\2", $target_file);
    $try++;
}

This will replace the file "duplicate.jpg" with "duplicate(1).jpg", then "duplicate(2).jpg", and so on.

It will still be prone to unlikely race conditions, just as using uniqid() or microtime() (which, conflict-wise, are both better).

Otherwise, always use tempnam(). You can check out this answer.

Community
  • 1
  • 1
LSerni
  • 55,617
  • 10
  • 65
  • 107