The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
The XMLHttpRequest Level 2 standard (still a working draft) defines the FormData
interface. This interface enables appending File
objects to XHR-requests (Ajax-requests).
Btw, this is a new feature - in the past, the "hidden-iframe-trick" was used (read about that in my other question).
This is how it works (example):
var xhr = new XMLHttpRequest(),
fd = new FormData();
fd.append( 'file', input.files[0] );
xhr.open( 'POST', 'http://example.com/script.php', true );
xhr.onreadystatechange = handler;
xhr.send( fd );
where input
is a <input type="file">
field, and handler
is the success-handler for the Ajax-request.
This works beautifully in all browsers (again, e开发者_运维百科xcept IE).
Now, I would like to make this functionality work with jQuery. I tried this:
var fd = new FormData();
fd.append( 'file', input.files[0] );
$.post( 'http://example.com/script.php', fd, handler );
Unfortunately, that won't work (an "Illegal invocation" error is thrown - screenshot is here). I assume jQuery expects a simple key-value object representing form-field-names / values, and the FormData
instance that I'm passing in is apparently incompatible.
Now, since it is possible to pass a FormData
instance into xhr.send()
, I hope that it is also possible to make it work with jQuery.
Update:
I've created a "feature ticket" over at jQuery's Bug Tracker. It's here: http://bugs.jquery.com/ticket/9995
I was suggested to use an "Ajax prefilter"...
Update:
First, let me give a demo demonstrating what behavior I would like to achieve.
HTML:
<form>
<input type="file" id="file" name="file">
<input type="submit">
</form>
JavaScript:
$( 'form' ).submit(function ( e ) {
var data, xhr;
data = new FormData();
data.append( 'file', $( '#file' )[0].files[0] );
xhr = new XMLHttpRequest();
xhr.open( 'POST', 'http://hacheck.tel.fer.hr/xml.pl', true );
xhr.onreadystatechange = function ( response ) {};
xhr.send( data );
e.preventDefault();
});
The above code results in this HTTP-request:
This is what I need - I want that "multipart/form-data" content-type!
The proposed solution would be like so:
$( 'form' ).submit(function ( e ) {
var data;
data = new FormData();
data.append( 'file', $( '#file' )[0].files[0] );
$.ajax({
url: 'http://hacheck.tel.fer.hr/xml.pl',
data: data,
processData: false,
type: 'POST',
success: function ( data ) {
alert( data );
}
});
e.preventDefault();
});
However, this results in:
As you can see, the content type is wrong...
I believe you could do it like this :
var fd = new FormData();
fd.append( 'file', input.files[0] );
$.ajax({
url: 'http://example.com/script.php',
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data){
alert(data);
}
});
Notes:
Setting
processData
tofalse
lets you prevent jQuery from automatically transforming the data into a query string. See the docs for more info.Setting the
contentType
tofalse
is imperative, since otherwise jQuery will set it incorrectly.
You can send the FormData object in ajax request using the following code,
$("form#formElement").submit(function(){
var formData = new FormData($(this)[0]);
});
This is very similar to the accepted answer but an actual answer to the question topic. This will submit the form elements automatically in the FormData and you don't need to manually append the data to FormData variable.
The ajax method looks like this,
$("form#formElement").submit(function(){
var formData = new FormData($(this)[0]);
//append some non-form data also
formData.append('other_data',$("#someInputData").val());
$.ajax({
type: "POST",
url: postDataUrl,
data: formData,
processData: false,
contentType: false,
dataType: "json",
success: function(data, textStatus, jqXHR) {
//process data
},
error: function(data, textStatus, jqXHR) {
//process error msg
},
});
You can also manually pass the form element inside the FormData object as a parameter like this
var formElem = $("#formId");
var formdata = new FormData(formElem[0]);
Hope it helps. ;)
There are a few yet to be mentioned techniques available for you. Start with setting the contentType property in your ajax params.
Building on pradeek's example:
$('form').submit(function (e) {
var data;
data = new FormData();
data.append('file', $('#file')[0].files[0]);
$.ajax({
url: 'http://hacheck.tel.fer.hr/xml.pl',
data: data,
processData: false,
type: 'POST',
// This will override the content type header,
// regardless of whether content is actually sent.
// Defaults to 'application/x-www-form-urlencoded'
contentType: 'multipart/form-data',
//Before 1.5.1 you had to do this:
beforeSend: function (x) {
if (x && x.overrideMimeType) {
x.overrideMimeType("multipart/form-data");
}
},
// Now you should be able to do this:
mimeType: 'multipart/form-data', //Property added in 1.5.1
success: function (data) {
alert(data);
}
});
e.preventDefault();
});
In some cases when forcing jQuery ajax to do non-expected things, the beforeSend
event is a great place to do it. For a while people were using beforeSend
to override the mimeType before that was added into jQuery in 1.5.1. You should be able to modify just about anything on the jqXHR object in the before send event.
I do it like this and it's work for me, I hope this will help :)
<div id="data">
<form>
<input type="file" name="userfile" id="userfile" size="20" />
<br /><br />
<input type="button" id="upload" value="upload" />
</form>
</div>
<script>
$(document).ready(function(){
$('#upload').click(function(){
console.log('upload button clicked!')
var fd = new FormData();
fd.append( 'userfile', $('#userfile')[0].files[0]);
$.ajax({
url: 'upload/do_upload',
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data){
console.log('upload success!')
$('#data').empty();
$('#data').append(data);
}
});
});
});
</script>
JavaScript:
function submitForm() {
var data1 = new FormData($('input[name^="file"]'));
$.each($('input[name^="file"]')[0].files, function(i, file) {
data1.append(i, file);
});
$.ajax({
url: "<?php echo base_url() ?>employee/dashboard2/test2",
type: "POST",
data: data1,
enctype: 'multipart/form-data',
processData: false, // tell jQuery not to process the data
contentType: false // tell jQuery not to set contentType
}).done(function(data) {
console.log("PHP Output:");
console.log(data);
});
return false;
}
PHP:
public function upload_file() {
foreach($_FILES as $key) {
$name = time().$key['name'];
$path = 'upload/'.$name;
@move_uploaded_file($key['tmp_name'], $path);
}
}
You can use the $.ajax beforeSend
event to manipulate the header.
…
beforeSend: function(xhr) {
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
}
…
See this link for additional information: http://msdn.microsoft.com/en-us/library/ms536752(v=vs.85).aspx
If you want to submit files using ajax use "jquery.form.js" This submits all form elements easily.
Samples http://jquery.malsup.com/form/#ajaxSubmit
rough view :
<form id='AddPhotoForm' method='post' action='../photo/admin_save_photo.php' enctype='multipart/form-data'>
<script type="text/javascript">
function showResponseAfterAddPhoto(responseText, statusText)
{
information= responseText;
callAjaxtolist();
$("#AddPhotoForm").resetForm();
$("#photo_msg").html('<div class="album_msg">Photo uploaded Successfully...</div>');
};
$(document).ready(function(){
$('.add_new_photo_div').live('click',function(){
var options = {success:showResponseAfterAddPhoto};
$("#AddPhotoForm").ajaxSubmit(options);
});
});
</script>
Instead of - fd.append( 'userfile', $('#userfile')[0].files[0]);
Use - fd.append( 'file', $('#userfile')[0].files[0]);
精彩评论