0
votes

I have a form that allows the user to upload multiple images, with each image capped at 2MB. After the form is submitted, the images would be stored on the server(E.g my computer in this case).

PROBLEM When uploading multiple files, the first image that is uploaded will always fail in uploading to the server, while the others(E.g 2nd,3rd, etc) are able to be saved to my computer successfully.When testing the form with just ONE image, the image also fails to upload.

I've concluded that the first image that is submitted through the form will always fail to upload though i fail to see why that is the case as i am able to echo the tmp_name of the image files successfully.

MY CODE(Extract):

  if(isset($_FILES['upload']['tmp_name']))
 {
$numfile=count($_FILES['upload']['tmp_name']);

    for($i=0;$i<$numfile;$i++)
    {
        if(!empty($_FILES['upload']['tmp_name'][$i]))
        {
            if(is_uploaded_file($_FILES['upload']['tmp_name'][$i]))
            {

                //Conditionals for uploaded file
                $foldername=$_SESSION['UserId'];
                $cat=$_POST['category'];
                $sub=$_POST['subcat'];
                $itemname=$_POST['itemname'];
                $allowed_filetypes=array('.jpg','.gif','.bmp','.png','.JPG');
                $max_filesize = 2097152; // Maximum filesize in BYTES (currently 2.0MB).
                $upload_path = 'C:\Users\Kence\Desktop\UniServer\www\images\\'.$foldername.'\\'.$cat.'\\'.$sub.'\\'.$itemname.'\\'; // The place the files will be uploaded to.

                //Checks if Folder for User exists
                //If not, A folder for the user is created to store the user's images
                if(!is_dir($upload_path))
                {
                    $upload_path=mkdir($upload_path,0644,true);
                }

                $filename = $_FILES['upload']['name'][$i]; // Get the name of the file (including file extension).
                $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.

                // Check if the filetype is allowed, if not DIE and inform the user.
                if(in_array($ext,$allowed_filetypes))
                {
                    if(filesize($_FILES['upload']['tmp_name'][$i])<$max_filesize)
                    {
                        if(is_writable($upload_path))
                        {echo"$upload_path <br>";
                        print_r($_FILES);
                            if(!move_uploaded_file($_FILES['upload']['tmp_name'][$i],"$upload_path" . $filename))
                            {
                                $errormsg="Upload Failed.Error in moving file";
                            }
                        }
                        else
                        {
                        $errormsg="Image Upload Failed.";
                        }
                    }
                    else
                    {
                        $errormsg="Upload failed.ONly images below 2MB are allowed";
                    }
                }
                else
                {
                    $errormsg="Error. Only JPEG,PNG and BMP files are allowed";
                }

            }
            else
            {
                $errormsg="Error.File not uploaded";
            }
        }
    }

}
else
{
$errormsg="Upload failed";
}

Error messages I get the error message

Error.File not uploaded

Form Code:

<body onload="getcategory()">
  <form action="<?PHP echo $_SERVER['PHP_SELF'] ?>" name="additem" enctype="multipart/form-data" method="POST">
<table>
<tr>
  <td>Select Category: </td><td>
    <select name="category" id="category" onchange="getsubcategory(this)">
      <option disabled="disabled" value="">Choose a category</option>
    </select>
  </td>
</tr>
<tr>
  <td>Select SubCategory</td>
  <td>
    <select id="subcat" name="subcat">
      <option value=""></option>
    </select>
  </td>
</tr>
<tr>
  <td>Item Name</td>
  <td><input type="text" name="itemname" size="30" maxlength="50" required="required"></td>
</tr>
<tr>
  <td>Item Price</td>
  <td><input type="number" name="itemprice" size="30" min="1" required="required"></td>
</tr>
<tr>
  <td>Item Info</td>
  <td><textarea name="iteminfo" col="40" rows="10" maxlength="300" required="required"></textarea>
</tr>

<tr>
  <td>Filename:</td>
  <td><input type="file" name="upload[]" /></td>
</tr>

<tr>
  <td>Filename:</td>
  <td><input type="file" name="upload[]" /></td>
</tr>

<tr>
  <td>Filename:</td>
  <td><input type="file" name="upload[]" /></td>
</tr>

<tr>
  <td>Filename:</td>
  <td><input type="file" name="upload[]" /></td>
</tr>

<tr>
  <td>Filename:</td>
  <td><input type="file" name="upload[]" /></td>
</tr>
<tr>
 <td colspan="2"><input type="SUBMIT" name="Button" value="Submit"></td>
</tr>
<tr>
  <td colspan="2"><?PHP if(isset($errormsg)){echo"$errormsg";}?></td>
</tr>       
<tr>
  <td colspan="3"><font color="#FF0000"></font></td>            
</tr> 

Even though i am able to print_r ($_FILES) and the tmp_name of all the images im trying to upload will display successfully.

EDIT Step Taken/Tried Added an if(!empty) check so that only uploads with tmp_name are processed.Empty uploads are thus ignored, thereby removing the error(Credits to Sven for his kind help)

Error.File not uploaded

However, even with that, the first image that is submitted to the form will NOT be saved(I.e if i upload just one image, if would fail,without any errors, and if i upload multiple images, only the first image would not be uploaded while the rest would be saved successfully.) However, if i were to refresh the page(thereby resubmitting the same form) the first image would then be saved.

The problem here is that the file path is NOT writable, causing the first image to not be saved.However what is confusing me is that, if the file path for the first image is not writable, why would the subsequent images have a valid file path, when they are running on the same code? Also, why would refreshing the page( and thus resubmitting the form) magically let the first image be saved successfully(which eans the file path is now writable?)

Results of my print_r($_FILES);

Array ( 
    [upload] => Array ( 
        [name] => Array ( 
            [0] => download (1).jpg 
            [1] => download.jpg 
            [2] => 
            [3] => 
            [4] => 
        ) 
        [type] => Array ( 
            [0] => image/jpeg 
            [1] => image/jpeg 
            [2] => 
            [3] => 
            [4] => 
        ) 
        [tmp_name] => Array ( 
            [0] => C:\Users\Kence\Desktop\UniServer\tmp\php474.tmp 
            [1] => C:\Users\Kence\Desktop\UniServer\tmp\php475.tmp 
            [2] => 
            [3] => 
            [4] => 
        ) 
        [error] => Array ( 
            [0] => 0 
            [1] => 0 
            [2] => 4 
            [3] => 4 
            [4] => 4 
        ) 
        [size] => Array ( 
            [0] => 6229 
            [1] => 6984 
            [2] => 0 
            [3] => 0 
            [4] => 0 
        ) 
    ) 
)

Could someone point out where and what im doing wrong? I've been trying for the past 3 hours and i still don't know what i'm doing wrong and it's driving me crazy!

EDIT:RESOLVED

Figured out my mistake.

I originally wrote

if(!is_dir($upload_path))
{
    $upload_path=mkdir($upload_path,0644,true);
}

and i changed it to

if(!is_dir($upload_path))
{
    mkdir($upload_path,0644,true);
}

Which solved the errors i was getting. Really stupid mistake on my part

3
I have a feeling it might be because of your file_exists() call. Have you tried manually creating the directory first, then sending the upload? Also, this question may be of some helpBojangles
It would help a lot if you clean up the bracket situation at the beginning and at the end. Indent it properly.Jim Martens
@Bojangles I've tried looking at the link provided and changed file_exists to realpath but it doesn't work.Upon submission of the form, only the second image gets uploaded. Only when i refresh the form(thereby making it upload twice) that both images get saved.Kenneth .J
Please add the output of your print_r($_FILES) call to your question.Sven
@Sven Hi sven, i've edited my post to include the results of my print_r($_FILES)Kenneth .J

3 Answers

1
votes

Look at your dump, and compare with your code.

Your code accesses ALL upload fields, even if there is no file uploaded, for example in fields 3, 4 and 5. So your code iterates over ALL these files and uses realpath() on an empty string.

This will trigger the error message "Error.File not uploaded". Which is correct because file number 3, 4 and 5 were not uploaded, they were left empty.

Your code has to deal with this.

And as a security feature, do not use realpath(), use is_uploaded_file(). PHP has a list of filenames that were created during the upload, and only those files should be allowed to process in the upload script. You do not want to touch any other files, even if an attacker tricked PHP into manipulating the "tmp_name".

0
votes

"upload" here $_FILES['upload'] refers to the name of the file field in the form.
you are only ckecking if a file from the file field named upload has been uploaded

did you maybe name the first upload field in the form differently?

0
votes

Figured out my mistake.

I originally wrote

if(!is_dir($upload_path))
{
    $upload_path=mkdir($upload_path,0644,true);
}

and i changed it to

if(!is_dir($upload_path))
{
    mkdir($upload_path,0644,true);
}

Which solved the errors i was getting. Really stupid mistake on my part.