Click to See Complete Forum and Search --> : avoid refresh button resubmitting forms


BigMoosie
11-26-2006, 11:17 AM
I have a form that is using php. If the user presses refresh on the page they are sent to then the POST values are resent and the php script runs again which causes problems, is there some HTML or PHP to fix this?
Thankyou very much
-moose

so_is_this
11-26-2006, 12:02 PM
About the only thing you can do is to send a unique id to the form as a hidden field and maintain a table of when these unique id's have been posted. Then, when receiving a post, you can check to see if that unique id has previously been posted.

chazzy
11-26-2006, 02:27 PM
The best way to handle this situation is to use a setup of

form - processor - confirmation

Form - the page where the user enters data
Processor - has no output, but processes the response of the form. typically keeps data in session
Confirmation - some kind of "thank you" or "try again" type of page, based on information in the session. will keep track of errors that might exist.

No need to use some kind of unique identifier. Note that nothing can really stop a user from resubmitting a page multiple times, it'll still get processed no matter. You can attempt to catch this via sessions, where you do a check to see if they are supposed to be on this page or not.

so_is_this
11-26-2006, 02:36 PM
Opinions vary on the "best way" to do a thing. My experience is that the "best way" to process a form is to have it submitting to itself -- as this makes it more logical to present form validation error messages and for users to make any needed corrections for resubmission. But... Each to their own.

chazzy
11-26-2006, 02:47 PM
Opinions vary on the "best way" to do a thing. My experience is that the "best way" to process a form is to have it submitting to itself -- as this makes it more logical to present form validation error messages and for users to make any needed corrections for resubmission. But... Each to their own.

I assume when you say "page" you mean a single file named "something".php, right? I'm also guessing you dont' use objects much. But, never did I say that any of this needs to be on different pages. It's just important that you use proper logic call flow to guide things.

Such as, if the $_POST array is not empty, then run the processor, else if the session variable formSubmitted is true, then we run the confirmation that can also redisplay the form on error, or even on completion. else, we just print out the form regularly.

Pezmc
11-26-2006, 02:58 PM
It best way i think is to hae a hidden field called notrun and then something like

if (isset($_POST['my_form'])) {
$notrun = $_POST['notrun'];

if ($notrun == "") { *Script goes here* } else { *oppositescript* }

bokeh
11-26-2006, 03:41 PM
In my opinion the "best way" is a 302 redirect to a landing page on success. That way if the refresh button is pressed all that will happen is the landing page will be refreshed.

so_is_this
11-26-2006, 05:01 PM
...and if the [Back] button is pressed followed by the [Refresh] button?

bokeh
11-27-2006, 01:23 AM
if the back button is pressed you will get back to the empty form loaded by the original GET request. If you press back and then refresh it will also reload that GET request, not the POST request.

BigMoosie
11-27-2006, 10:33 AM
The 302 approach is sounding the most sound for this use, the script is only going to be used for an administrator panel by one person so it doesnt have to be perfect, but pressing refresh will cause unusual things to happen so i was just looking for the simplest way to avoid this. The unique id approach i just couldn't be bothered to do but I agree would be the most ideal.

so_is_this
11-27-2006, 10:33 AM
Is that something a 302 does? Because I normally see the [Back] and [Refresh] causing a resubmit of the same post data.

bokeh
11-27-2006, 12:14 PM
Is that something a 302 does? Because I normally see the [Back] and [Refresh] causing a resubmit of the same post data.Have a play with the simple script below. You will find the only way to send a POST request is by pressing the submit button. Pressing refresh on the other hand only submits a GET request. <?php

if(isset($_GET['success'])) # success page
{
echo 'The form submitted ok!';
die;
}
elseif(isset($_POST['submit'])) # handle form here
{
$error = null;

# validate form here... on success send 302
if('form validates')
{
header('Location: http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?success');
die;
}
else # handle errors here
{
$error = "Some relevant error message here!<br>\n";
}
}

echo $error;

# load/reload sticky form
?><form action="" method="post">
<input type="submit" name="submit" value="submit">
</form>

so_is_this
11-27-2006, 01:03 PM
I don't see any 302 in there. What was mentioning 302 all about?

bokeh
11-27-2006, 01:13 PM
I don't see any 302 in there. What was mentioning 302 all about?...

header() (http://www.php.net/header): The second special case is the "Location:" header. Not only does it send this header to the browser, but it also returns a REDIRECT (302) status code to the browser unless some 3xx status code has already been set.

so_is_this
11-27-2006, 01:40 PM
Oh, I didn't know that using the Location header sends a 302 status.
So, the 302 status is what cancels the post data?

bokeh
11-27-2006, 02:05 PM
302 doesn't cancel anything. The post data is still sent and validated. Different status numbers signify different things to the browser. 3xx is always some kind of redirect. A 302 response tells the browser the requested resource resides temporarily under a different URI. The relevant RFC (http://www.faqs.org/rfcs/rfc2616.html) is not completely clear on how a 302 should be handled but all modern browsers retrieve the resource specified by the Location: header using the GET method and with out the need for user intervention. Since the browser has been advised that the resource the POST data was sent to has temporarily moved no amount of pressing the refresh button will convince it to resubmit the form to that resource.

so_is_this
11-27-2006, 02:25 PM
302 doesn't cancel anything. The post data is still sent and validated.
Duh! That is not what I said -- nor what was being talked about. The subject was re-sending the post data. Thus, of course! the post data is initially sent. That all happens *before* the redirect is done to the success page. So, you should have correctly understood my question to mean, "So, the 302 status is what cancels [resending] the post data?"
Since the browser has been advised that the resource the POST data was sent to has temporarily moved no amount of pressing the refresh button will convince it to resubmit the form to that resource.
You've now confirmed that the correct answer to my question is, "Yes." Thanks.

bokeh
11-27-2006, 02:49 PM
Duh! That is not what I saidso_is_this I am not attempting to put words in your mouth. This board is read by people, many of whom do not share English as their mother tongue. My purpose is to make any response I post as clear and useful as possible to all its readers.

BigMoosie
11-27-2006, 11:06 PM
Have a play with the simple script below. You will find the only way to send a POST request is by pressing the submit button. Pressing refresh on the other hand only submits a GET request.

This depends on the browser, firefox for instance opens a popup asking if you would like to resend the POST data.

bokeh
11-28-2006, 05:00 AM
This depends on the browser, firefox for instance opens a popup asking if you would like to resend the POST data.Not with my script posted above!

matt00
11-28-2006, 07:42 AM
I have a similar problem, when my page with the form loads up it automatically sends a blank email to me......can i paste in something like the 302 approach somewhere to stop this from hapening?

my php code is as follows:


<?php

include "MIME.class";
define('TO', 'me@myemail.on.net'); # CHANGE THIS TO A REAL ADDRESS (yours?)

// Has there been a form submission? If yes, go on and
// process...
if (is_array($HTTP_POST_VARS)) {

if ($resume != 'none') {
$fname = './'.$resume_name; // make a real filename
// Get the content-type of the uploaded file

if (preg_match("!/x\-.+!i", $resume_type))
$type = OCTET;
else
$type = $resume_type;

$from = sprintf("'%s' <%s>", $name, $email) ;
copy($resume, $fname); //do error checking if need
$mime = new MIME_mail($from, TO, 'online application form', "Please find attached the resume from the online application form from $name", "Cc: $email");
$mime->fattach($fname, "Resume of $name", $type);
$mime->send_mail();
} else {
echo "Dear $name<p>You have not submitted your resume. Please use the browse button to attach it and click send!<br>";
}
}
?>

bokeh
11-28-2006, 08:12 AM
I have a similar problemYour problem is here: if (is_array($HTTP_POST_VARS)) {$HTTP_POST_VARS is always an array.

BigMoosie
11-28-2006, 09:07 AM
Not with my script posted above!
Right you are.

matt00
11-28-2006, 04:39 PM
Your problem is here: if (is_array($HTTP_POST_VARS)) {$HTTP_POST_VARS is always an array.


ah thanks, but what can I replace/change this with?

matt00
11-28-2006, 07:59 PM
Also with the code i pasted in above, does anyone know how I can get it to put all the files that people send into a folder, say called "resumes". Instead of just storing them in the same flder as the website?

so_is_this
11-28-2006, 11:13 PM
Also with the code i pasted in above, does anyone know how I can get it to put all the files that people send into a folder, say called "resumes". Instead of just storing them in the same flder as the website?
If I understand your question, the intent is that you use the following function to move uploaded files from their temporary location and name to their more permanent resting place and name:

move_uploaded_file ( string filename, string destination )

matt00
11-28-2006, 11:28 PM
move_uploaded_file ( string filename, string destination )

Where do i put that in the code? and how would it look (in the code) if the destination folder was called "resumes"?

sorry im not good at this stuff.... :s

so_is_this
11-28-2006, 11:34 PM
You need to read this:

Handling File Uploads (http://www.php.net/manual/en/features.file-upload.php)

matt00
11-29-2006, 01:52 AM
Thanx, I read the site and found some information but I cant work out how to adapt "move_uploaded_file" to my code...........

matt00
11-29-2006, 05:28 AM
ok well i tried putting it in but its not dooing what its supposed to...the form and file still sends but its not moving the file into the folder.....

<?php

include "MIME.class";
define('TO', 'btstudio@internode.on.net'); # CHANGE THIS TO A REAL ADDRESS (yours?)

// Has there been a form submission? If yes, go on and
// process...
if (is_array($HTTP_POST_VARS)) {

if ($resume != 'none') {
$fname = './'.$resume_name; // make a real filename
// Get the content-type of the uploaded file

if (preg_match("!/x\-.+!i", $resume_type))
$type = OCTET;
else
$type = $resume_type;

$from = sprintf("'%s' <%s>", $name, $email) ;
copy($resume, $fname); //do error checking if need
$mime = new MIME_mail($from, TO, 'online application form', "Please find attached the resume from $name", "Cc: $email");
$mime->fattach($fname, "Resume of $name", $type);
$mime->send_mail();
} else {

if (move_uploaded_file($_FILES["resume_name"]["uploaded_resumes"]))

echo "Dear $name<p>You have not submitted your resume. Please use the browse button to attach it and click send!<br>";
}
}
?>


so i got there.....(is it in the right spot?)

if (move_uploaded_file($_FILES["resume_name"]["uploaded_resumes"]))

is that right?
the files names are "resume_name" and i made a folder on the server called "uploaded_resumes".........


thanx for your help by the way

so_is_this
11-29-2006, 11:55 AM
so i got there.....(is it in the right spot?)

if (move_uploaded_file($_FILES["resume_name"]["uploaded_resumes"]))

is that right?
the files names are "resume_name" and i made a folder on the server called "uploaded_resumes"...
The format for the function is as follows:

move_uploaded_file ( string filename, string destination )

so your's is incorrect.

matt00
11-29-2006, 03:57 PM
I realise that but cant u give me a correct answer seeing i cant figure it out?....please

so_is_this
11-29-2006, 05:45 PM
All you have to do is follow the example given on that page. That function requires two arguments -- you are only giving it one (and that one is wrong). The first argument needs to keep the ['tmp_name'] part shown in the example on that page. The first argument represents the FROM file name and the second argument represents the TO file path and name.
You need to read this:

Handling File Uploads (http://www.php.net/manual/en/features.file-upload.php)

matt00
11-29-2006, 08:36 PM
is it correct now if i place this in there:


$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads";
$uploaddir.="resume_name";

//Copy the file to some permanent location
if (move_uploaded_file($_FILES["resume_name"]["tmp_name"], $uploaddir))

so_is_this
11-30-2006, 12:57 AM
You didn't quite follow the example on that page. This:

$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads";
$uploaddir.="resume_name";

should be more like this:

$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads/";
$uploadfile .= "resume_name/" . basename($_FILES['resume_name']['name']);

In other words, as I said:
...the second argument represents the TO file path and name.

matt00
11-30-2006, 08:02 AM
ok cool thanx, well this is it but its still not moving the file...could you have a look over it for me and fix what it wrong as someother people i know also cannot see why its not moving the file

<?php

include "MIME.class";
define('TO', 'me@myemail.on.net'); # CHANGE THIS TO A REAL ADDRESS (yours?)

// Has there been a form submission? If yes, go on and
// process...
if($_POST){

if ($resume != 'none') {
$fname = './'.$resume_name; // make a real filename
// Get the content-type of the uploaded file

if (preg_match("!/x\-.+!i", $resume_type))
$type = OCTET;
else
$type = $resume_type;

$from = sprintf("'%s' <%s>", $name, $email) ;
copy($resume, $fname); //do error checking if need
$mime = new MIME_mail($from, TO, 'online application form', "Please find attached the resume from $name", "Cc: $email");
$mime->fattach($fname, "Resume of $name", $type);
$mime->send_mail();
} else
{
$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/uploads/";
$uploadfile .= "resume_name/" . basename($_FILES['resume_name']['name']);

//Copy the file to some permanent location
if (move_uploaded_file($_FILES["resume_name"]["tmp_name"], $uploaddir, $uploadfile))

echo "Dear $name<p>You have not submitted your resume. Please use the browse button to attach it and click send!<br>";
}
}
?>

matt00
11-30-2006, 08:04 AM
and also the permisions of the file are set so it can copy it there as i found a code that just moves the file but doesnt email it and that works..... :S

so_is_this
11-30-2006, 01:46 PM
Sorry, I overlooked the switch-a-roo you pulled on me... The example showed using the same variable:

$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads/";
$uploaddir .= "resume_name/" . basename($_FILES['resume_name']['name']);

but you slipped in another variable:

$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads/";
$uploadfile = "resume_name/" . basename($_FILES['resume_name']['name']);

So your function call should be like this:

if (move_uploaded_file($_FILES["resume_name"]["tmp_name"], $uploaddir . $uploadfile))
______________________________________________________________________^

matt00
11-30-2006, 05:34 PM
ah sorry thats how the example put it.......sorta....

well changing that still didnt do it....do u want to see my whole form code to see if there is somthing in there?

so_is_this
11-30-2006, 05:52 PM
Just post that same section -- as you have it now.

matt00
11-30-2006, 05:58 PM
<?php

include "MIME.class";
define('TO', 'me@myemail.on.net'); # CHANGE THIS TO A REAL ADDRESS (yours?)

// Has there been a form submission? If yes, go on and
// process...
if($_POST){

if ($resume != 'none') {
$fname = './'.$resume_name; // make a real filename
// Get the content-type of the uploaded file

if (preg_match("!/x\-.+!i", $resume_type))
$type = OCTET;
else
$type = $resume_type;

$from = sprintf("'%s' <%s>", $name, $email) ;
copy($resume, $fname); //do error checking if need
$mime = new MIME_mail($from, TO, 'online application form', "Please find attached the resume from $name", "Cc: $email");
$mime->fattach($fname, "Resume of $name", $type);
$mime->send_mail();
} else
{
$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/uploads/";
$uploadfile = "resume_name/" . basename($_FILES['resume_name']['name']);

//Copy the file to some permanent location
if (move_uploaded_file($_FILES["resume_name"]["tmp_name"], $uploaddir . $uploadfile))

echo "Dear $name<p>You have not submitted your resume. Please use the browse button to attach it and click send!<br>";
}
}
?>




And also some1 said:

first up is this line..

if ($resume != 'none')

I don't see any declaration of 'resume' anywhere in your code.
Let's assume that somewhere you've got
$resume = $_POST['resume']

Does that effect it moving the file?

so_is_this
11-30-2006, 06:21 PM
I would think you want something like this:
<?php
if($_SERVER['REQUEST-TYPE'] == 'POST') {
if($_FILES['resume_name']['tmp_name'] == 'none') {
echo "<p>Dear $name</p>\n<p>You have not submitted your resume. Please use the browse button to attach it and click send!</p>\n";
} else {
if(!is_uploaded_file($_FILES['resume_name']['tmp_name'])) {
echo "<p>Possible file upload attack!</p>\n";
exit;
}

$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/uploads/";
$uploadfile = "resume_name/" . basename($_FILES['resume_name']['name']);

if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $uploadfile)) {
echo "<p>File is valid, and was successfully uploaded.</p>\n";
} else {
echo "<p>File move falied.</p>\n";
}
}
}
?>

matt00
11-30-2006, 06:23 PM
but thats not going to email it to me is it?

so_is_this
11-30-2006, 06:24 PM
Just add that part in. I'm not going to do *everything* for you! ;)

matt00
11-30-2006, 06:29 PM
ok, do i replace what i have with that then.......where do u put that in....after the :

<?php

include "MIME.class";
define('TO', 'me@myemail.on.net'); # CHANGE THIS TO A REAL ADDRESS (yours?)


under here?

Meni
12-01-2006, 01:03 PM
I have a VERY unusual way in which i deal with important form submissions.
I am pretty sure that some of you will find it extremely stupid - but it works for me.

I use a javascript function to submit the form to a _new page and then close it.


This should go in your <head> section:

<script language=javascript>
<!--
function submitMyForm()
{
document.formname.action = "your_form_action_page.php"
document.newissue.target = "_blank"; // a new window
document.newissue.submit(); // Submit
window.location.href="/index.php"; // redirect this window to some kind of "Your form was successfully submitted page"
return true;
}

-->
</script>

And at the bottom of your your_form_action_page.php page:

echo "<script>javascript:window.open('/close.html', '_self');</script>";


You may ask yourselves - why would i redirect to ANOTHER page to close this window... well this is due to an annoying question if using IE7. It will not allow you to close the page. it will ask the user if it's OK first.

SO - in close.html, I have:

<html><body>
<script language="JavaScript">window.close();</script>
</body></html>



Again - this may not be the smartest thing to do - but i am sure getting a sound night's sleep with this.