Forum Moderators: coopster
For instance the problem I am having now is that my form seems to wait about the time it would take to upload the file and the returns a warning that a missing field is required. Also, I have a form captcha (enter the weird characters). Id like the form to check the required fields then the form captcha and then perform the upload.
How would I do this in php?
Right now I am making the move_uploaded_file the last thing to happen, but even if the form has errors it delays the time it would take for the upload.
1) Split the submission:
Run the main part of the form in an IFRAME, have the submit button below the upload part (not in an IFRAME) actually submit the IFRAME's form (use javascript). In the return from the IFRAME, send an instruction through Javascript's DOM to the main page to submit the upload form (obviously only send this instruction if the form was ok - if not redisplay for entry). In this way you can keep sending back the main part of the form without having to send the file each time, until it's ready - in which case the form will trigger submission of the upload form part and complete the process. Note you will need to cache the successful form submission data from the main part - $_SESSION should be a good option here ($_SESSION['post']=$_POST). This approach does not degrade well without Javascript - you need to think about that.
2) Use Client Side Javascript
This works best in my opinion - basically write Javascript to duplicate all your PHP form validity checks. The only problem with this (apart from the extra work involved) is that you won't be able to safely run CAPTCHA this way as it splits the two processes and opens the door for easy CAPTCHA bypass methods.
3) Using Shockwave Flash.
Flash allows you not to submit the file at the same time as you submit the data; in fact it will allow you to submit the file immediately and have it uploading whilst you fill in the rest of the form, retry things, etc. until you get it right. That's a serious advantage - and worth consideration. Down side is you need to build that part in Flash; it won't work if users don't have the Flash player - and it's fiddly if you've not done it before.
And after re-reading option one, its seems like kind of a hack but one worth looking into. Could you elaborate on that some more and maybe post some example code?
When you get the form submission, do the move_uploaded_file() etc. bit straight away; store the file somewhere (temp if required) and record the fact that it's already stored in $_SESSION. Now - if the rest of the form doesn't check out - send it back to them with errors marked, but miss out the upload file field (you already have this) - instead show them the file name, size and type with a button [change this file] which triggers an upload file field to be added via DOM.
Now - when the form is resubmitted, and you get to the file handling bit, you will know from $_SESSION that you already have one, and can use that file wherever you stored it.
If you are sure you'll remember to remove it on the next page load, you could even store the file temporarily into $_SESSION as binary... just be sure not to leave it there very long.
As for the rest ------
drooh:-
Re: 3 (flash) - I've only been involved in custom-built ones (they are reasonably simple and code is around if you have flash to compile it with) - so I can't help too much there.
Re: 1 (iframe):
IFRAME /mainbit.php
Field name [-------------]
Field name [-------------]
Upload file [------------[Browse]]
[Submit]
Submit button: onClick --> get the IFRAME's object in JS and then call submit on the first form inside it; return false (don't submit)
mainbit.php --> when submitted (this happens only via the parent page) check it - if not right, redisplay with errors marked. If right: Store the data in $_SESSION, then return just a javascript call to parent document to submit the first form there - this will not trigger the onClick for the submit there, and the main form will submit.
mainpage.php --> now you got a POST you know that the iframe form was previously submitted and you got the data in $_SESSION - you also have the file upload in $_FILES:
$_POST=$_SESSION['post'] (to simplify things... grab stuff back from SESSION so you can start thinking of things as a single submit)
Now deal with inserts etc. as per usual...
what if they never get the captcha correct? How long does the file stay in temporary?
/usr/bin/find /var/www/html/temp_files/ -ctime +10 -type f -exec rm {} -f \; the name of this file is upload.php
<?php
session_start();
if(isset($_GET['end'])){
session_unset();
}
$image_set = false;
$image_prev_set = false;
$code_er = null;
$name = null;
$name_er = null;
$email = null;
$email_er = null;
$file_type_er = null;
$file_type_error = false;
$required_pass = true;
$code_pass = false;
if(isset($_POST['sub'])){
$name = $_POST['name'];
$email = $_POST['email'];
if(!$email){
$email_er = "required field";
$required_pass = false;
}
if(isset($_POST['code'])){
$code = $_POST['code'];
if($code == "123"){
$_SESSION['code_pass'] = true;
$code_er = "the code you entered is correct";
} else {
$_SESSION['code_pass'] = false;
$code_er = "the code you entered is wrong";
}
}
if(isset($_SESSION['code_pass'])){
if($_SESSION['code_pass'] == true){
$code_pass = true;
} else {
$code_pass = false;
}
}
if(isset($_FILES['image']['name'])){
if($_FILES['image']['name'] != ""){
$image_set = true;
}
}
if(isset($_SESSION['image_prev_set'])){
if($_SESSION['image_prev_set']){
$image_prev_set = true;
$image_set = true;
}
}
if(!$image_prev_set and $image_set){
$file_array = array("image/gif","image/jpeg","image/pjpeg");
if (!in_array($_FILES["image"]["type"],$file_array)){
$file_type_error = true;
$file_type_er = "Invalid file type".$_FILES["image"]["type"];
$image_set = false;
} else {
$_SESSION['file'] = file_get_contents($_FILES["image"]["tmp_name"]);
$_SESSION['filename'] = $_FILES["image"]["name"];
$_SESSION['filetype'] = $_FILES["image"]["type"];
$_SESSION['filesize'] = $_FILES["image"]["size"];
$_SESSION['image_prev_set'] = true;
$image_set = true;
$file_type_error = false;
}
}
if($required_pass AND $code_pass AND $image_set AND !$file_type_error){
echo "here";
$newfile = fopen("up/".$_SESSION['filename'], 'w');
file_put_contents("up/".$_SESSION['filename'],$_SESSION['file']);
} else {
$imgset_codefail = true;
$_SESSION['imgset_codefail'] = true;
}
}
?>
<a href="upload.phtml?start">start</a>
<a href="upload.phtml?end">end</a>
<form method="POST" enctype="multipart/form-data" action="upload.php">
<p>name: <input type="text" name="name" size="20" value="<?=$name?>" /><?=$name_er?></p>
<p>* email: <input type="text" name="email" size="20" value="<?=$email?>" /><?=$email_er?></p>
<p>
<? if(!$image_set): ?>
<input type="file" name="image" size="20"><?=$file_type_er?>
<? else: ?>
<? echo "<img src=\"img.jpg\" width=\"20\" align=\"absmiddle\" /> <b>".$_SESSION['filename']."</b> ".$_SESSION['filesize']."kb<br />"; ?>
<? endif; ?>
</p>
<p>
<? if(!$code_pass): ?>
123<br />code: <input type="text" name="code" size="20"><?=$code_er?>
<? else: ?>
you entered a valid code
<? endif; ?>
</p>
<p><input type="submit" value="Submit" name="sub"></p>
</form>
the confirmation code is just 123 on this, obviously it would be substituted for a form captcha.
you will also need an image of a generic file and call it img.jpg