arrays - PHP form file upload: 2 inputs but only attaching 1 file
Get the solution ↓↓↓I have being trying to figure this out for a while and just can't seem to get it. I have a working code for one file upload which works fine and now trying to create one for 2 uploads. To attempt to add multiple files I have added a foreach loop and switched the name attribute of the form input to name="photo[]" so that it reads an array. The form submits with no errors but I still only receive the first file in the email attachments. I have seen lot's of similar questions but still can't get it- thank you for your patience! (I have also played around with:
for($i = 0; $i < 2; $i++) {
in place of and aswell as foreach) but here is my current code.
HTML Form:
<form enctype="multipart/form-data" method= "post" action="couple_uploader_test.php">
<input type="hidden" name="myEmail" value="[email protected]">
<input type="hidden" name="subject" value="Couple Portrait Order">
<label>Name:</label><input type="text" name="customerName" required="true"/><br/>
<label>Email:</label><input type="email" name="customerEmail" required="true"/><br/>
<label>Photo:</label><input type="file" name="photo[]" accept="image/*" required="true"/>
<label>2nd Photo (optional):</label><input type="file" name="photo[]" accept="image/*"/>
<label>Notes:</label><textarea name="message" cols="30" rows="6">customer message here</textarea>
<input type="hidden" name="thankyou_url" value="http://www.website.co.uk/html/couple_uploaded.html"/>
<input type="submit" value="Submit Photo"/>
</form>
Uploader PHP:
<?php
$to = $_POST['myEmail'];
$from = $_POST['customerEmail'];
$name = $_POST['customerName'];
$subject = $_POST['subject'];
$message = $_POST['message']."\n\n" . $name;
$message = wordwrap($message,70);
foreach ($_FILES['photo']['name'] as $key => $tmp_name) {
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["photo"]["name"][$key]);
$extension = end($temp);
if ((($_FILES["photo"]["type"][$key] == "image/gif")
|| ($_FILES["photo"]["type"][$key] == "image/jpeg")
|| ($_FILES["photo"]["type"][$key] == "image/jpg")
|| ($_FILES["photo"]["type"][$key] == "image/pjpeg")
|| ($_FILES["photo"]["type"][$key] == "image/x-png")
|| ($_FILES["photo"]["type"][$key] == "image/png"))
&& ($_FILES["photo"]["size"][$key] < 3000000)
&& in_array($extension, $allowedExts)) {
/* GET File Variables */
$tmpName = $_FILES['photo']['tmp_name'][$key];
$fileType = $_FILES['photo']['type'][$key];
$fileName = $_FILES['photo']['name'][$key];
/* Start of headers */
$headers = "From: $from";
if (file($tmpName)) {
/* Reading file ('rb' = read binary) */
$file = fopen($tmpName,'rb');
$data = fread($file,filesize($tmpName));
fclose($file);
/* a boundary string */
$randomVal = md5(time());
$mimeBoundary = "==Multipart_Boundary_x{$randomVal}x";
/* Header for File Attachment */
$headers .= "\nMIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed;\n" ;
$headers .= " boundary=\"{$mimeBoundary}\"";
/* Multipart Boundary above message */
$message = "This is a multi-part message in MIME format.\n\n" .
"--{$mimeBoundary}\n" .
"Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$message . "\n\n";
/* Encoding file data */
$data = chunk_split(base64_encode($data));
/* Adding attchment-file to message*/
$message .= "--{$mimeBoundary}\n" .
"Content-Type: {$fileType};\n" .
" name=\"{$fileName}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" .
"--{$mimeBoundary}--\n";
}
} else {
echo "Invalid File.";
}
}
$sent = mail($to, $subject, $message, $headers);
if ($sent) {
echo '<meta http-equiv="refresh" content="0;url=http://website.co.uk/html/thankyou.html">';
} else {
echo "Sorry, we have encoutered a problem sending your message. Please try again or get in touch via the contact page";
}
?>
Ideally I need it to loop through 2 input file types (the second one being optional so if a user just uploads one image it will still work) and attach them to one single email. Thank you.
Answer
Solution:
Move$headers
and$message
to outside of yourfor
loop. You already have$message
outside, but you are overwriting it with this code:
/* Multipart Boundary above message */
$message = "This is a multi-part message in MIME format.\n\n" .
"--{$mimeBoundary}\n" .
"Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$message . "\n\n";
It should be:
/* Multipart Boundary above message */
$message .= "This is a multi-part message in MIME format.\n\n" .
"--{$mimeBoundary}\n" .
"Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$message . "\n\n";
PS: You can redirect in PHP like so:
header('Location: http://website.co.uk/html/thankyou.html');
Another PS: You should secure against errors by checking things are set in the$_POST
array before trying to access them like so:
$to = isset($_POST['myEmail']) ? $_POST['myEmail'] : NULL;
This is a ternary operator, which is basically shorthand for:
if(isset($_POST['myEmail'])) {
$to = $_POST['myEmail']
} else {
$to = NULL;
}
Answer
Solution:
When your loop runs it rewrite both the $message and the $headers variables from scratch instead of concatenating. So when you actually send the email the attached file is only one.
Answer
Solution:
If you use the foreach loop correctly to get each uploaded file one at a time so you can process it, you would end up with something like this.
I have not checked the actual contents of header are correct I just assumed you had it right, but I did simplify some of the coding and remove the unnecessary creation of scalar variables to hold data that was already there in the $_FILES array in a perfectly usable state.
/* a boundary string */
$randomVal = md5(time());
$allowedExts = array("gif", "jpeg", "jpg", "png");
/* Start of headers */
$headers = "From: $from";
$mimeBoundary = "==Multipart_Boundary_x{$randomVal}x";
/* Header for File Attachment */
$headers .= "\nMIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed;\n" ;
$headers .= " boundary=\"{$mimeBoundary}\"";
/* Multipart Boundary above message */
$message = "This is a multi-part message in MIME format.\n\n" .
"--{$mimeBoundary}\n" .
"Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$message . "\n\n";
foreach ($_FILES['photo'] as $filenumber => $file) {
$temp = explode(".", $file["name"]);
$extension = end($temp);
if ( ($file["type"] == "image/gif"
|| $file["type"] == "image/jpeg"
|| $file["type"] == "image/jpg"
|| $file["type"] == "image/pjpeg"
|| $file["type"] == "image/x-png"
|| $file["type"] == "image/png" )
&& $file["size"] < 3000000
&& in_array($extension, $allowedExts))
{
if ( file($file['tmp_name']) ) {
/* Reading file ('rb' = read binary) */
$fh = fopen($file['tmp_name'],'rb');
$data = fread($fh,filesize($file['tmp_name']));
fclose($fh);
/* Encoding file data */
$data = chunk_split(base64_encode($data));
/* Adding attchment-file to message*/
$message .= "--{$mimeBoundary}\n" .
"Content-Type: {$file['type']};\n" .
" name=\"{$file['name']}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" .
"--{$mimeBoundary}--\n";
}
} // endif
} // endforeach
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: git was not found in your path, skipping source download
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.