/    Sign up×
Community /Pin to ProfileBookmark

avoid refresh button resubmitting forms

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

to post a comment
PHP

45 Comments(s)

Copy linkTweet thisAlerts:
@so_is_thisNov 26.2006 — 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.
Copy linkTweet thisAlerts:
@chazzyNov 26.2006 — 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.
Copy linkTweet thisAlerts:
@so_is_thisNov 26.2006 — 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.
Copy linkTweet thisAlerts:
@chazzyNov 26.2006 — 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.[/QUOTE]

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.
Copy linkTweet thisAlerts:
@PezmcNov 26.2006 — It best way i think is to hae a hidden field called notrun and then something like

[code=php] if (isset($_POST['my_form'])) {

$notrun = $_POST['notrun'];

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

[/code]
Copy linkTweet thisAlerts:
@bokehNov 26.2006 — In my opinion the "[I]best way[/I]" 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.
Copy linkTweet thisAlerts:
@so_is_thisNov 26.2006 — ...and if the [Back] button is pressed followed by the [Refresh] button?
Copy linkTweet thisAlerts:
@bokehNov 27.2006 — 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.
Copy linkTweet thisAlerts:
@BigMoosieauthorNov 27.2006 — 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.
Copy linkTweet thisAlerts:
@so_is_thisNov 27.2006 — Is that something a 302 does? Because I normally see the [Back] and [Refresh] causing a resubmit of the same post data.
Copy linkTweet thisAlerts:
@bokehNov 27.2006 — Is that something a 302 does? Because I normally see the [Back] and [Refresh] causing a resubmit of the same post data.[/QUOTE]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. [code=php]<?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>[/code]
Copy linkTweet thisAlerts:
@so_is_thisNov 27.2006 — I don't see any 302 in there. What was mentioning 302 all about?
Copy linkTweet thisAlerts:
@bokehNov 27.2006 — I don't see any 302 in there. What was mentioning 302 all about?[/QUOTE]...

[URL=http://www.php.net/header]header()[/URL]: 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.[/QUOTE]
Copy linkTweet thisAlerts:
@so_is_thisNov 27.2006 — Oh, I didn't know that using the Location header sends a 302 status.

So, the 302 status is what cancels the post data?
Copy linkTweet thisAlerts:
@bokehNov 27.2006 — 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 [url=http://www.faqs.org/rfcs/rfc2616.html]relevant RFC[/url] is not completely clear on how a 302 should be handled but all modern browsers retrieve the resource specified by the [I]Location:[/I] 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.
Copy linkTweet thisAlerts:
@so_is_thisNov 27.2006 — 302 doesn't cancel anything. The post data is still sent and validated.[/QUOTE]
Duh! That is not what I said -- nor what was being talked about. The subject was [U]re-sending[/U] 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.[/QUOTE]
You've now confirmed that the correct answer to my question is, "Yes." Thanks.
Copy linkTweet thisAlerts:
@bokehNov 27.2006 — Duh! That is not what I said[/QUOTE]so_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.
Copy linkTweet thisAlerts:
@BigMoosieauthorNov 28.2006 — 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.[/QUOTE]

This depends on the browser, firefox for instance opens a popup asking if you would like to resend the POST data.
Copy linkTweet thisAlerts:
@bokehNov 28.2006 — This depends on the browser, firefox for instance opens a popup asking if you would like to resend the POST data.[/QUOTE]Not with my script posted above!
Copy linkTweet thisAlerts:
@matt00Nov 28.2006 — 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:

[CODE]
<?php

include "MIME.class";
define('TO', '[email protected]'); # 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>";
}
}
?>
[/CODE]
Copy linkTweet thisAlerts:
@bokehNov 28.2006 — I have a similar problem[/QUOTE]Your problem is here:[code=php] if (is_array($HTTP_POST_VARS)) {[/code]$HTTP_POST_VARS is always an array.
Copy linkTweet thisAlerts:
@BigMoosieauthorNov 28.2006 — Not with my script posted above![/quote]
Right you are.
Copy linkTweet thisAlerts:
@matt00Nov 28.2006 — Your problem is here:[code=php] if (is_array($HTTP_POST_VARS)) {[/code]$HTTP_POST_VARS is always an array.[/QUOTE]


ah thanks, but what can I replace/change this with?
Copy linkTweet thisAlerts:
@matt00Nov 29.2006 — 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?
Copy linkTweet thisAlerts:
@so_is_thisNov 29.2006 — 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?[/QUOTE]
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 )
Copy linkTweet thisAlerts:
@matt00Nov 29.2006 — move_uploaded_file ( string filename, string destination )[/QUOTE]

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
Copy linkTweet thisAlerts:
@so_is_thisNov 29.2006 — You need to read this:

[URL=http://www.php.net/manual/en/features.file-upload.php]Handling File Uploads[/URL]
Copy linkTweet thisAlerts:
@matt00Nov 29.2006 — Thanx, I read the site and found some information but I cant work out how to adapt "move_uploaded_file" to my code...........
Copy linkTweet thisAlerts:
@matt00Nov 29.2006 — 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.....

[CODE]<?php

include "MIME.class";
define('TO', '[email protected]'); # 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>";
}
}
?>[/CODE]



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
Copy linkTweet thisAlerts:
@so_is_thisNov 29.2006 — 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"...[/QUOTE]

The format for the function is as follows:

move_uploaded_file ( string filename, string destination )

so your's is incorrect.
Copy linkTweet thisAlerts:
@matt00Nov 29.2006 — I realise that but cant u give me a correct answer seeing i cant figure it out?....please
Copy linkTweet thisAlerts:
@so_is_thisNov 29.2006 — 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 [B][COLOR=Blue]['tmp_name'][/COLOR][/B] part shown in the example on that page. The first argument represents the [B][COLOR=Red]FROM[/COLOR][/B] file name and the second argument represents the [B][COLOR=Red]TO[/COLOR][/B] file path and name.
You need to read this:

[URL=http://www.php.net/manual/en/features.file-upload.php]Handling File Uploads[/URL][/QUOTE]
Copy linkTweet thisAlerts:
@matt00Nov 30.2006 — 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))
Copy linkTweet thisAlerts:
@so_is_thisNov 30.2006 — 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[COLOR=Red][B]/[/B][/COLOR]";

$uploadfile .= "resume_name[COLOR=Red][B]/[/B][/COLOR]" . [COLOR=Red]basename($_
FILES['resume_name']['name'])[/COLOR];

In other words, as I said:
...the second argument represents the TO file path [COLOR=Red][B][U]and[/U][/B][/COLOR] name.[/QUOTE]
Copy linkTweet thisAlerts:
@matt00Nov 30.2006 — 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

[CODE]<?php

include "MIME.class";
define('TO', '[email protected]'); # 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>";
}
}
?>[/CODE]
Copy linkTweet thisAlerts:
@matt00Nov 30.2006 — 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
Copy linkTweet thisAlerts:
@so_is_thisNov 30.2006 — Sorry, I overlooked the switch-a-roo you pulled on me... The example showed using the same variable:
[CODE]
$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads/";
[COLOR=Blue]$uploaddir[/COLOR] .= "resume_name/" . basename($_FILES['resume_name']['name']);[/CODE]


but you slipped in another variable:
[CODE]
$uploaddir = $_SERVER['DOCUMENT_ROOT']."/home/montica/mainwebsite_html/uploads/";
[COLOR=Red]$uploadfile[/COLOR] = "resume_name/" . basename($_FILES['resume_name']['name']);[/CODE]


So your function call should be like this:
[CODE]
if (move_uploaded_file($_FILES["resume_name"]["tmp_name"], $uploaddir [COLOR=Red][B].[/B][/COLOR] $uploadfile))
______________________________________________________________________^[/CODE]
Copy linkTweet thisAlerts:
@matt00Nov 30.2006 — 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?
Copy linkTweet thisAlerts:
@so_is_thisNov 30.2006 — Just post that same section -- as you have it now.
Copy linkTweet thisAlerts:
@matt00Nov 30.2006 — [CODE]<?php

include "MIME.class";
define('TO', '[email protected]'); # 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>";
}
}
?>[/CODE]





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'][/QUOTE]


Does that effect it moving the file?
Copy linkTweet thisAlerts:
@so_is_thisDec 01.2006 — I would think you want something like this:
[code=php]<?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";
}
}
}
?>[/code]
Copy linkTweet thisAlerts:
@matt00Dec 01.2006 — but thats not going to email it to me is it?
Copy linkTweet thisAlerts:
@so_is_thisDec 01.2006 — Just add that part in. I'm not going to do *everything* for you! ?
Copy linkTweet thisAlerts:
@matt00Dec 01.2006 — ok, do i replace what i have with that then.......where do u put that in....after the :

<?php

include "MIME.class";

define('TO', '[email protected]'); # CHANGE THIS TO A REAL ADDRESS (yours?)


under here?
Copy linkTweet thisAlerts:
@MeniDec 01.2006 — 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:
[CODE]
<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>[/CODE]


And at the bottom of your your_form_action_page.php page:

[code=php]echo "<script>javascript:window.open('/close.html', '_self');</script>";[/code]


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:

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




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

Success!

Help @BigMoosie spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.25,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...