I have a form which includes a bunch of text and date fields as well as a "file" input (see below)
<button class="contact100-form-upload-btn" id="uploadbutton" type="button" onclick="document.getElementById('uploadedfile').click()">Upload Picture Identification </button>
<input style="display:none" name="uploadedfile" id="uploadedfile" onchange="selectfile()" type="file" accept="image/*" />
function selectfile() {
var x = document.getElementById("progdiv");
x.style.display = "block";
var file = _("uploadedfile").files[0];
//alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append("uploadedfile", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "file_upload_parser.php?confnum=" + <?php echo $confnum ?> + "&file=1");
ajax.send(formdata);
formData.delete(uploadedfile);
document.getElementById("uploadbutton").style.backgroundColor = "#FF5733";
document.getElementById("uploadbutton").innerHTML = "Photo Uploading";
}
The selectfile() function is a nice file upload function using Ajax which shows a little upload status bar so the user knows what's going on. All of this functionality works perfectly and the file uploads to the sever. The issue is when I submit the form, the file get's uploaded again which sort of defeats the purpose of uploading it with Ajax. Is there a way to make an input field (file) not be part of a form, or delete the file element from the from altogether (as it has already been uploaded) before submitting it? Or maybe another way I am totally missing?
Any help will be greatly appreciated.
-Lawrence
What worked for me was to remove multipart/form-data from the form so it ignores file uploads.
"When you are writing client-side code:
use multipart/form-data when your form includes any elements
otherwise you can use multipart/form-data or application/x-www-form-urlencoded but application/x-www-form-urlencoded will be more efficient"
This solution will obviously not work if you want to upload some files but solved my issue.
Related
I'm trying to get a simple upload system going using php and XMLHttpRequest. However I fail to achieve the goal using the request. It doesn't work..
Here is my HTML form which is used to get the image file:
<form action="../session/uploader.php" method="post" enctype="multipart/form-data" id="uploadForm">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>
and this is my PHP script which saves the image into my filesystem:
<?php
if(isset($_POST["submit"])) {
$target_dir = "../db/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
}
?>
Now this works perfectly fine but I want to use an XMLHttpRequest so that the page doesn't need to refresh when images are uploaded. I was trying to do something which seemed very straight forward but it didn't work..
first I changed the PHP to this:
<?php
$target_dir = "../db/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
?>
and right below my form in the HTML I've added some Javascript which makes the XMLHttpRequest and sends it:
<script>
const uploadForm = document.getElementById("uploadForm");
uploadForm.addEventListener("submit", function(e) {
e.preventDefault();
const xhr = new XMLHttpRequest();
xhr.open("POST", "../session/uploader.php", true);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.send(new FormData(uploadForm));
});
</script>
The problem here is that it simply doesn't work. Nothing happens. I get no feedback. It's like the uploader.php script didn't get called.
Doesn anyone know what the problem might be?
if(isset($_POST["submit"]))
The submit button will not be included in the form submission data set here, as it would be if you had just send the form “normally”.
xhr.send(new FormData(uploadForm));
The browser has no idea here at this point, that you clicked the submit button to actually trigger the whole process - so it will only include the data for the fileToUpload file upload field, but not the submit button.
You can either add a hidden field, and then check if that is set within $_POST, or you check if fileToUpload is set directly (but remember, that one is going to be in $_FILES, not $_POST.)
xhr.setRequestHeader("Content-Type", "multipart/form-data");
A proper multipart request also needs to include the boundary that will be used to separate the parts inside the request body, in this header.
Using FormData, this should automatically get added, so remove this line - it is overwriting the correct header with one that is incomplete here at this point.
I am trying to submit a form via ajax using the post method and a FormData object.
Here is a simplified version of the JavaScript:
var form=…; // form element
var url=…; // action
form['update'].onclick=function(event) { // button name="update"
var xhr=new XMLHttpRequest();
xhr.open('post',url,true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var formData=new FormData(form);
formData.append('update', true); // makes no difference
xhr.send(formData);
xhr.onload=function() {
alert(this.response);
};
};
The form has:
a button (type="button" name="update") to run the script
no action and method="get"
My PHP script has the following:
if(isset($_POST['update'])) {
print_r($_POST);
exit;
}
// more stuff
print 'other stuff';
When I try it, the PHP falls through to the rest of the code, and I get the other output, rather than what I expect from the print_r statement.
I have tried the following variations:
new FormData() (without the form). This does work if I add the update data manually.
new FormData(form). This does not work, whether I add the update manually or not.
changing the form method to post.
Firefox, Safari & Chrome on MacOS; all current versions.
The from itself looks something like this:
<form id="edit" method="post" action="">
<p><label for="edit-summary">Summary</label><input id="edit-summary" name="summary" type="text"></p>
<p><label for="edit-description">Description</label><input id="edit-description" name="description" type="text"></p>
<p><label for="edit-ref">Reference</label><input id="edit-ref" name="ref" type="text"></p>
<p><label for="edit-location">Location</label><input id="edit-location" name="location" type="text"></p>
<p><button type="button" name="update">OK</button></p>
</form>
What should I do to submit the get this to work?
No jQuery, please.
The content type when sending a FormData object is multipart/form-data not url encoded.
Further more the proper boundary must be set for the request, which the user is unable to do. For this XMLHttpRequest sets the correct content type with the required boundary.
So all you have to do is not set the content type and it'll work.
var xhr=new XMLHttpRequest();
xhr.open('post',url,true);
//xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");<--don't do this
var formData=new FormData(form);
formData.append('update', true); // makes no difference
xhr.send(formData);
xhr.onload=function() {
alert(this.response);
};
Change the name of the button to something other than "update" (and change it in your form['update'].onclick... as well). I think its clashing with the value you are trying to set on the FormData to trigger the PHP code.
I’m going crazy with image upload to Facebook. I’ve tried HTML5 drag and drop methods, Dropzone.js, as well as uploading to my own server before submitting the image via PHP. But the only one I can make work (because of my inexperience, I’ll admit) and that doesn't involve uploading the image to my own server, is by using a HTML form as shown in the Facebook documentation:
<form id=“upload_form” enctype="multipart/form-data" action=“https://graph.facebook.com/event_id/photos?access_token=an_access_token” method="POST">
Please choose a photo
<input name="source" type="file"><br/><br/>
Say something about this photo:
<input name="message" type="text" value=""><br/><br/>
<input type="submit" value="Upload"/><br/>
</form>
I dynamically generate it in Javascript and use var’s to fill in event_id and access_token.
This works fine, so all my permissions and authorising are correct. Now what I’d like to do is handle the response because the browser does as you’d expect when the user clicks submit and displays basic text showing the post id and whatnot.
So, I created a button and bound the following to it’s click event:
var fd = document.getElementById('upload_form');
if (fd) {
console.log('Sending');
var XHR = new XMLHttpRequest();
XHR.addEventListener('load', function(data) {
console.log('XHR finished:');
console.log(data);
});
XHR.addEventListener('error', function(data) {
console.log('XHR ERROR:');
console.log(data);
});
var graph_url = 'https://graph.facebook.com/'+event_id+'/photos?access_token=' + access_token;
XHR.open('POST', graph_url);
XHR.send(fd);
}
Once the user has selected an image and clicks my button to execute the above XHR completes the send and reports as finished, but Facebook replies with:
(#324)Requires upload file.
Please can someone show me where I’ve gone wrong - it’s been a problem for days now!
If you willing to use jquery and jquery.ajaxForm plugin
<!-- You form code stay Make sure your form.action url is valid ajaxForm use that as url -->
<form id=“upload_form” enctype="multipart/form-data" action=“https://graph.facebook.com/event_id/photos?access_token=an_access_token” method="POST">
Please choose a photo
<input name="source" type="file"><br/><br/>
Say something about this photo:
<input name="message" type="text" value=""><br/><br/>
<input type="submit" value="Upload"/><br/>
</form>
//your javascript to upload the image togather with message
// put this in a button, not submit button
$('#upload_form').ajaxForm({
complete: function(data) {
//process fb response
}
});
I suggest you use Fiddler to catch both connections, with and without XMLHttpRequest and see which is the actual difference between both request, I don't actually know what XHR.send(fd); does, but maybe it's sending the form content itself, not submitting it?
Fiddler is a very useful tool when connecting to external APIs
I have a website that manages where people are and what they are doing at work and if they need help or not.
I am using phone gap in order to make my application and I was wondering if it is possible to take a button on the phone gap and have javascript fill out a form on my webpage and then submit it so I can then process that data?
The form that I am trying to connect to is. I process this form in python through flask:
<form action="" method="POST" id = "stuff">
<dl>
<dt>
<input type=text name=gc>
<input type=text name=cursquad>
<input type=text name=trap>
<input type=text name=scrtkey>
<input type="submit">
</form>
You could use an AJAX post request with jquery, but then you'll need jquery in your phonegap, which might be quite overkill only for this.
Therefor I'd recommend this approach:
<script>
function loadXMLDoc() {
var url = "http://example.com";
var parameters = "foo=bar&bar=baz"; // Construct you form values like field=value&field2=value2&...
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var response = xmlhttp.responseText;
}
}
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-length", parameters.length);
xmlhttp.setRequestHeader("Connection", "close");
xmlhttp.send(parameters);
}
</script>
This will POST all the data you put into parameters to the url you give. If you point it to your form page it should work.
If it doesn't, (jquery approach doesn't work out of the box), you might have to add some headers to the receiving page to allow it to receive data from external pages. The Access-Control-Allow-Origin header is needed here, where you can provide a list of safe domains. Since your application is not on a domain though, you could add this to your receiving page (Assuming you are running php):
header('Access-Control-Allow-Origin: *');
Try running it without first though, as it opens your form for everyone.
I want to have a callback after my form has successfully been submitted. This form does not reload the page and the ajax alternative is not available to us because of "cross origin" issues.
What I have now is:
$('#uploadform form').on('submit', function(){
// DO STUFF HERE
});
But this is firing as soon as submit event is triggered and not as a callback. Without using ajax, how do I make code run after and only after the response is received (and get the response to do stuff with)? Is this even possible?
It is through AWS's S3 file hosting and cannot use JSONP.
I would rather not use an iframe if I don't have to for simplicity's sake.
EDIT
It doesn't reload the page just like a file download link doesn't reload the page. Otherwise it's exactly like any other form. It's not submitted inside of an iframe. It's a normal form, but the headers involved don't require the page to reload.
A solution has come to me that will allow me to submit my form without reloading the page, not use an iframe or JSONP, and while it probably technically counts as AJAX, it does not have this same "cross origin" issue.
function uploadFile() {
var file = document.getElementById('file').files[0];
var fd = new FormData();
fd.append('key', "${filename}");
fd.append("file",file);
xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open('POST', 'http://fake-bucket-name.s3-us-west-1.amazonaws.com/', true); //MUST BE LAST LINE BEFORE YOU SEND
xhr.send(fd);
}
function uploadProgress(evt) {
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}
function uploadComplete(evt) {
/* This event is raised when the server send back a response */
alert("Done - " + evt.target.responseText );
}
function uploadFailed(evt) {
alert("There was an error attempting to upload the file." + evt);
}
function uploadCanceled(evt) {
alert("The upload has been canceled by the user or the browser dropped the connection.");
}
With a simple form like this:
<form id="form1" enctype="multipart/form-data" method="post">
<div class="row">
<label for="file">Select a File to Upload</label><br>
<input type="file" name="file" id="file">
</div>
<div id="fileName"></div>
<div id="fileSize"></div>
<div id="fileType"></div>
<div class="row">
<input type="button" onclick="uploadFile()" value="Upload">
</div>
<div id="progressNumber"></div>
</form>
The uploadComplete(evt) function being the callback. As you can see, it also gives you the percentage complete you can show your users.
Note: To do this you have to set the correct upload policy and CORS
policy in your S3 account.
– RonSper
You will run into 'cross origin' issues with ajax and iframes equally if you need access to the response.
JSONP is the only way around your 'cross-origin' issues. It is what is used by all JSON APIs that are hosted on a different domain, unless you try to use CORS which isn't supported in legacy IE versions.
If you can control the server where the form is submitted you should be able to make it return a JSONP compatible response. If not, you are kind of out of luck.