Alex
Alex

Reputation: 35781

Upload multiple files with PHP

I'm trying to use this code to upload multiple files with PHP 5.5 and attach to an email. If I take the brackets from file[] (so it's file) on the name attribute of the input field, I'm able to successfully upload one file; if I put the brackets back on, the page gives this warning (for the line with the call to file_get_contents()) and attaches a file to the email called Array.dat but not the selected file. What am I doing wrong?

Warning: file_get_contents() expects parameter 1 to be a valid path, array given in C:\wamp\www\myapp\submit.php on line 188

HTML:

<input id="file" name="file[]" type="file" multiple="true">

PHP:

$fullmessage = "This is a multi-part fullname in MIME format.

--_1_$boundary
Content-Type: multipart/alternative; boundary=\"_2_$boundary\"

--_2_$boundary
Content-Type: text/plain; charset=\"iso-8859-1\"
Content-Transfer-Encoding: quoted-printable

$msg_quoted

--_2_$boundary--\r\n";

$msg_b64 = base64_encode($msg);

$fullmessage .= "--_1_$boundary
Content-Type: application/octet-stream; name=\"".$date->format('U')."-".$company."-".$custname."-".$email.".txt\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment

$msg_b64\r\n";

foreach($_FILES as $f){
  if($f['size'] > 0){
  $attachment = chunk_split(base64_encode(file_get_contents($f['tmp_name'])));
   $name = $f['name'];

   $fullmessage .= "--_1_$boundary
Content-Type: application/octet-stream; name=\"$name\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment

$attachment\r\n";
  }
}

$fullmessage .= "--_1_$boundary--";
$mail_options = '';
$mail_options .= 'O DeliveryMode=b'; //tells sendmail to run asynchronously
mail(EMAIL_RECIPIENTS, $subject, $fullmessage, $headers, $mail_options);

Update: This fixed it, thanks to @I'L'I:

// Process the uploaded files.
$num_files = count($_FILES['file']['tmp_name']);

for($i=0; $i < $num_files; $i++){   
    if($_FILES['file']['size'][$i] > 0){
        $attachment = chunk_split(base64_encode(file_get_contents($_FILES['file']['tmp_name'][$i])));
        $name = $_FILES['file']['name'][$i];

        $fullmessage .= "--_1_$boundary
Content-Type: application/octet-stream; name=\"$name\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment

$attachment\r\n";
  }  
}

Upvotes: 1

Views: 523

Answers (2)

l&#39;L&#39;l
l&#39;L&#39;l

Reputation: 47159

I think this problem is more a matter of what the error indicates:

Warning: file_get_contents() expects parameter 1 to be a valid path, array given in C:\wamp\www\myapp\submit.php on line 188.

file_get_contents expects a string, not an array.

So there's a couple of things you can do to fix this:

Either use the correct string:

  $attachment = chunk_split(base64_encode(file_get_contents($f)));

Or use the key of the $_FILES array

for ($x=0; $x<sizeof($_FILES); $x++) {
    $attachment = chunk_split(base64_encode(file_get_contents($_FILES[$x])));
} 

Upvotes: 1

Sven
Sven

Reputation: 70853

You cannot usually upload more than one file with only one file input element. The only browser I encountered that supports it was Opera, and they removed the feature, probably because of lack of server side support.

And that is exactly what you are experiencing: If you change the name of the form field from being a single name into pointing to an array, you have to change the access to the file data on the PHP side. If you say you cannot use a decent library for mailing, I assume you cannot change the PHP code that receives the files. Then you cannot change the one-file upload into a multi-file upload.

And please consider not trying to create such a multi-file input field on the HTML side because no user is knowing that he might be able to send more than one file - and even if you tell them they can, they don't know how.

Upvotes: 1

Related Questions