it-swarm.com.de

Wie sende ich FormData-Objekte mit Ajax-Anfragen in jQuery?

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:

multipartformdata

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:

wrongcontenttype

Wie Sie sehen, ist der Inhaltstyp falsch ...

452
Šime Vidas

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 .

815
pradeek

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.

28
BenSwayne

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. ;)

18
Lucky

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

5
dmnkhhn

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>   
5
talalalshehri

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);
    }
}
3
Rahul Yadav

Anstelle von - fd.append( 'userfile', $('#userfile')[0].files[0]);

Verwenden Sie - fd.append( 'file', $('#userfile')[0].files[0]);

2
user4757231

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>
2
Rohit