Der Standard XMLHttpRequest Level 2 (noch ein funktionierender Entwurf) definiert die Schnittstelle FormData
. Diese Schnittstelle ermöglicht das Anhängen von File
Objekten an XHR-Requests (Ajax-Requests).
Übrigens ist dies ein neues Feature - in der Vergangenheit wurde der "Hidden-Iframe-Trick" verwendet (lesen Sie darüber in meine andere Frage ).
So funktioniert es (Beispiel):
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 );
wobei input
ein <input type="file">
-Feld ist und handler
der Erfolgshandler für die Ajax-Anfrage ist.
Dies funktioniert wunderbar in allen Browsern (außer IE).
Jetzt möchte ich diese Funktionalität mit jQuery arbeiten lassen. Ich habe es versucht:
var fd = new FormData();
fd.append( 'file', input.files[0] );
$.post( 'http://example.com/script.php', fd, handler );
Leider funktioniert das nicht (es wird ein Fehler "Illegaler Aufruf" ausgegeben - Screenshot hier ). Ich gehe davon aus, dass jQuery ein einfaches Schlüsselwertobjekt erwartet, das Formularfeldnamen/-werte darstellt, und die FormData
-Instanz, die ich übergebe, ist anscheinend nicht kompatibel.
Da es nun möglich ist, eine FormData
-Instanz an xhr.send()
zu übergeben, hoffe ich, dass es auch möglich ist, sie mit jQuery zum Laufen zu bringen.
Update:
Ich habe ein "Feature Ticket" bei jQuery's Bug Tracker erstellt. Es ist hier: http://bugs.jquery.com/ticket/9995
Mir wurde vorgeschlagen, einen "Ajax-Vorfilter" zu verwenden ...
Update:
Lassen Sie mich zunächst eine Demo geben, die zeigt, welches Verhalten ich erreichen möchte.
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();
});
Der obige Code führt zu dieser HTTP-Anfrage:
Das ist, was ich brauche - Ich möchte den Inhaltstyp "Mehrteilig/Formulardaten"!
Die vorgeschlagene Lösung wäre wie folgt:
$( '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();
});
Dies führt jedoch zu:
Wie Sie sehen, ist der Inhaltstyp falsch ...
Ich glaube, Sie könnten es so machen:
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);
}
});
Wenn Sie processData
auf false setzen, können Sie verhindern, dass jQuery die Daten automatisch in eine Abfragezeichenfolge umwandelt. Weitere Informationen finden Sie in den Dokumenten .
Das Setzen von contentType
auf false ist unabdingbar, da es andernfalls von jQuery falsch gesetzt wird .
Es stehen Ihnen noch einige zu erwähnende Techniken zur Verfügung. Beginnen Sie mit dem Festlegen der contentType -Eigenschaft in Ihren Ajax-Parametern.
Aufbauend auf Pradeeks Beispiel:
$('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 einigen Fällen ist das Ereignis beforeSend
ein großartiger Ort, um jQuery ajax dazu zu zwingen, unerwartete Dinge zu tun. Eine Weile benutzten Leute beforeSend
, um den mimeType zu überschreiben, bevor er in jQuery in 1.5.1 hinzugefügt wurde. Sie sollten in der Lage sein, so gut wie alles am jqXHR-Objekt im Before-Send-Ereignis zu ändern.
Sie können das FormData-Objekt in einer Ajax-Anforderung mit dem folgenden Code senden:
$("form#formElement").submit(function(){
var formData = new FormData($(this)[0]);
});
Dies ist der akzeptierten Antwort sehr ähnlich, aber eine tatsächliche Antwort für das Fragethema. Dadurch werden die Formularelemente automatisch in FormData übergeben, und Sie müssen die Daten nicht manuell an die FormData-Variable anhängen.
Die Ajax-Methode sieht so aus,
$("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
},
});
Sie können das Formularelement auch manuell innerhalb des FormData-Objekts als Parameter übergeben
var formElem = $("#formId");
var formdata = new FormData(form[0]);
Ich hoffe es hilft. ;)
Sie können das Ereignis $ .ajax beforeSend
verwenden, um den Header zu bearbeiten.
…
beforeSend: function(xhr) {
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
}
…
Weitere Informationen finden Sie unter diesem Link: http://msdn.Microsoft.com/en-us/library/ms536752 (v = vs.85) .aspx
Ich mache es so und es ist Arbeit für mich, ich hoffe das wird helfen :)
<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);
}
}
Anstelle von - fd.append( 'userfile', $('#userfile')[0].files[0]);
Verwenden Sie - fd.append( 'file', $('#userfile')[0].files[0]);
Wenn Sie Dateien mit Ajax senden möchten, verwenden Sie "jquery.form.js". Dadurch werden alle Formularelemente einfach gesendet.
Beispiele http://jquery.malsup.com/form/#ajaxSubmit
grobe Sicht:
<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>