I successfully use pjax for links and forms (GET
as well as POST
). But now I have a form which also has to send an <input type="file"...>
. Since pjax does not support this, I had a look at https://github.com/malsup/form (jquery.form plugin) which does support submitting form data with files, but not in the "pjax" way of working with browser history objects.
So, how would it be possible to use pjax functionality with forms that contain file fields? Any ideas?
Edit: The reason why I do not simply use FormData objects, but the jquery.form plugin: Internet Explorer can not handle them. And the plugin has a workaround for this browser. I do not insist of using jquery.form plugin, but I need a way to make it work with all the major browsers.
It seems like you may need to use a FormData
object in your AJAX/pJAX request which can process files. You can read more on the Mozilla Developer Network.
For example, if this is your form:
<form enctype="multipart/form-data">
<input name="file" type="file" />
<input type="button" value="Upload" />
</form>
First get the file contents like so:
var formData = new FormData($('form')[0]);
Then you could use a jQuery $.ajax
request or a simple XMLHttpRequest();
like so:
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://foo.com/processfile.php");
xhr.send(formData);
Or similarly in jQuery:
$.ajax({
url: 'http://foo.com/processfile.php',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false
});
On the server side, in processfile.php
, you can receive/display the file contents with:
$file = $_FILES['file']['name'];
This should work with pJAX as it is asynchronous! Just make sure you place this request BEFORE your pJAX request, or if you're using jQuery, you can add it as part of the success callback. For example (without knowing which pJAX library you are using):
$.ajax({
url: 'http://foo.com/processfile.php',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(data) {
$.pjax({url: url, container: '#pjax-container'});
}
});
Edit: If you would like to support IE7+, you need to fallback to using a hidden iframe element for the upload as FormData is only supported in Internet Explorer 10. A great plugin for submitting files which I have tested and works without jQuery is http://fineuploader.com/ which in my opinion is better/easier to use than the https://github.com/malsup/form (jquery.form plugin).
jQuery Ajax code
jQuery('document').ready(function(){
var input = document.getElementById("imagefile");
var formdata = false;
if (window.FormData) {
formdata = new FormData();
}
input.addEventListener("change", function (evt) {
var i = 0, len = this.files.length, img, reader, file;
for ( ; i < len; i++ ) {
file = this.files[i];
//validation to check whether uploaded files are images
if (!!file.type.match(/image.*/)) {
if ( window.FileReader ) {
reader = new FileReader();
reader.onloadend = function (e) {
};
reader.readAsDataURL(file);
}
if (formdata) {
//send the ajax query to upload the file(s)
jQuery.ajax({
url: "upload.php",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function (result) {
jQuery('div#response').html("Successfully uploaded").fadeOut();
}
});
}
}
else
{
alert('Not a vaild image!');
}
}
}, false);
});
HTML Code
<form enctype="multipart/form-data">
<input id="imagefile" type="file" name="image" accept="image/*"/ />
</form>
What above code will do for you is, once you upload the file(s) it will 1st of validate the type of the image and upload it via ajax for you. You can do multiple file uploads if you need. If you ever wonder what FormData
does,
The
FormData
object lets you compile a set of key/value pairs to send using XMLHttpRequest. Its primarily intended for use in sending form data, but can be used independently from forms in order to transmit keyed data. The transmitted data is in the same format that the form's submit() method would use to send the data if the form's encoding type were set to "multipart/form-data".
What addEventListener does for you is,
addEventListener() registers a single event listener on a single target. The event target may be a single element in a document, the document itself, a window, or an XMLHttpRequest.
You can use upload.php
to upload the file(s) at the server level.
If you want to have the this functionality in a plugin you can extend the plugin with the above code and it will not brick your plugin because this is a very straight forward code snippet which gets the job done. I have successfully integrated the code to a plugin with no issues at all.
If you have any issues let me know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With