Multipart/formdata mit jQuery.ajax senden

Lesezeit: 1 Minute

Multipartformdata mit jQueryajax senden
zoku

Ich habe ein Problem beim Senden einer Datei an ein serverseitiges PHP-Skript mit der Ajax-Funktion von jQuery. Es ist möglich, die Dateiliste mit zu erhalten $('#fileinput').attr('files') aber wie ist es möglich, diese Daten an den Server zu senden? Das resultierende Array ($_POST) auf dem serverseitigen PHP-Skript ist 0 (NULL) bei Verwendung der Dateieingabe.

Ich weiß, dass es möglich ist (obwohl ich bis jetzt keine jQuery-Lösungen gefunden habe, nur Prototypcode (http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html)).

Dies scheint relativ neu zu sein, also erwähnen Sie bitte nicht, dass das Hochladen von Dateien über XHR/Ajax unmöglich wäre, da es definitiv funktioniert.

Ich brauche die Funktionalität in Safari 5, FF und Chrome wären nett, sind aber nicht zwingend erforderlich.

Mein Code ist jetzt:

$.ajax({
    url: 'php/upload.php',
    data: $('#file').attr('files'),
    cache: false,
    contentType: 'multipart/form-data',
    processData: false,
    type: 'POST',
    success: function(data){
        alert(data);
    }
});

  • Leider funktioniert die Verwendung des FormData-Objekts unter IE<10 nicht.

    – Alejandro García Iglesias

    13. Mai 2013 um 16:52 Uhr

  • @GarciaWebDev angeblich können Sie ein Polyfill mit Flash verwenden, um dieselbe API zu unterstützen. Kasse github.com/Modernizr/Modernizr/wiki/… Für mehr Information.

    – Yuxhuang

    12. Juli 2013 um 4:09 Uhr

  • Mögliches Duplikat.

    – Raffael Schweikert

    26. März 2014 um 13:19 Uhr

  • Sie können verwenden $(':file') um alle Eingabedateien auszuwählen. Es ist nur ein bisschen einfacher.

    – Schahar

    20. August 2015 um 12:03 Uhr

  • @RameshwarVyevhare Diese Antwort wurde fünf Jahre nach der Beantwortung dieser Frage veröffentlicht. Bitte trollen Sie keine ähnlichen Fragen, nur um Ihre eigenen Antworten zu fördern.

    – kitti

    10. April 2017 um 23:48 Uhr

Multipartformdata mit jQueryajax senden
Raffael Schweikert

Ab Safari 5/Firefox 4 ist es am einfachsten, die zu verwenden FormData Klasse:

var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
    data.append('file-'+i, file);
});

Jetzt hast du also eine FormData -Objekt, das bereit ist, zusammen mit der XMLHttpRequest gesendet zu werden.

jQuery.ajax({
    url: 'php/upload.php',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    method: 'POST',
    type: 'POST', // For jQuery < 1.9
    success: function(data){
        alert(data);
    }
});

Es ist zwingend erforderlich, dass Sie die festlegen contentType Option zu falsewodurch jQuery gezwungen wird, a nicht hinzuzufügen Content-Type Header für Sie, da sonst die Begrenzungszeichenfolge fehlt. Außerdem müssen Sie die verlassen processData Flag auf „false“ gesetzt, andernfalls versucht jQuery, Ihre zu konvertieren FormData in eine Zeichenfolge, die fehlschlagen wird.

Sie können die Datei jetzt in PHP abrufen mit:

$_FILES['file-0']

(Es gibt nur eine Datei, file-0es sei denn, Sie haben die angegeben multiple Attribut in Ihrer Dateieingabe, in diesem Fall werden die Zahlen mit jeder Datei erhöht.)

Verwendung der FormData-Emulation für ältere Browser

var opts = {
    url: 'php/upload.php',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    method: 'POST',
    type: 'POST', // For jQuery < 1.9
    success: function(data){
        alert(data);
    }
};
if(data.fake) {
    // Make sure no text encoding stuff is done by xhr
    opts.xhr = function() { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; }
    opts.contentType = "multipart/form-data; boundary="+data.boundary;
    opts.data = data.toString();
}
jQuery.ajax(opts);

Erstellen Sie FormData aus einem vorhandenen Formular

Anstatt die Dateien manuell zu iterieren, kann das FormData-Objekt auch mit dem Inhalt eines bestehenden Formularobjekts erstellt werden:

var data = new FormData(jQuery('form')[0]);

Verwenden Sie anstelle eines Zählers ein natives PHP-Array

Benennen Sie Ihre Dateielemente einfach gleich und beenden Sie den Namen in Klammern:

jQuery.each(jQuery('#file')[0].files, function(i, file) {
    data.append('file[]', file);
});

$_FILES['file'] ist dann ein Array, das die Datei-Upload-Felder für jede hochgeladene Datei enthält. Ich empfehle dies tatsächlich gegenüber meiner ursprünglichen Lösung, da es einfacher ist, darüber zu iterieren.

1646125868 724 Multipartformdata mit jQueryajax senden
Assad Ullah

Schauen Sie sich meinen Code an, er erledigt die Arbeit für mich

$( '#formId' )
  .submit( function( e ) {
    $.ajax( {
      url: 'FormSubmitUrl',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
    e.preventDefault();
  } );

1646125868 53 Multipartformdata mit jQueryajax senden
ajmicek

Ich wollte nur etwas zu Raphaels großartiger Antwort hinzufügen. Hier erfahren Sie, wie Sie PHP dazu bringen, dasselbe zu produzieren $_FILESunabhängig davon, ob Sie zum Senden JavaScript verwenden.

HTML-Formular:

<form enctype="multipart/form-data" action="/test.php" 
method="post" class="putImages">
   <input name="media[]" type="file" multiple/>
   <input class="button" type="submit" alt="Upload" value="Upload" />
</form>

PHP erzeugt diese $_FILESwenn ohne JavaScript gesendet:

Array
(
    [media] => Array
        (
            [name] => Array
                (
                    [0] => Galata_Tower.jpg
                    [1] => 518f.jpg
                )

            [type] => Array
                (
                    [0] => image/jpeg
                    [1] => image/jpeg
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/phpIQaOYo
                    [1] => /tmp/phpJQaOYo
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )

            [size] => Array
                (
                    [0] => 258004
                    [1] => 127884
                )

        )

)

Wenn Sie eine progressive Verbesserung durchführen, verwenden Sie Raphaels JS, um die Dateien einzureichen …

var data = new FormData($('input[name^="media"]'));     
jQuery.each($('input[name^="media"]')[0].files, function(i, file) {
    data.append(i, file);
});

$.ajax({
    type: ppiFormMethod,
    data: data,
    url: ppiFormActionURL,
    cache: false,
    contentType: false,
    processData: false,
    success: function(data){
        alert(data);
    }
});

… das ist es, was PHP ist $_FILES Das Array sieht nach Verwendung dieses JavaScripts zum Senden folgendermaßen aus:

Array
(
    [0] => Array
        (
            [name] => Galata_Tower.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpAQaOYo
            [error] => 0
            [size] => 258004
        )

    [1] => Array
        (
            [name] => 518f.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpBQaOYo
            [error] => 0
            [size] => 127884
        )

)

Das ist ein nettes Array und tatsächlich das, was manche Leute transformieren $_FILES hinein, aber ich finde es nützlich, damit zu arbeiten $_FILES, unabhängig davon, ob JavaScript zum Senden verwendet wurde. Also, hier sind einige kleinere Änderungen am JS:

// match anything not a [ or ]
regexp = /^[^[\]]+/;
var fileInput = $('.putImages input[type="file"]');
var fileInputName = regexp.exec( fileInput.attr('name') );

// make files available
var data = new FormData();
jQuery.each($(fileInput)[0].files, function(i, file) {
    data.append(fileInputName+'['+i+']', file);
});

(Bearbeitung vom 14. April 2017: Ich habe das Formularelement aus dem Konstruktor von FormData() entfernt – das hat diesen Code in Safari behoben.)

Dieser Code macht zwei Dinge.

  1. Ruft die ab input name-Attribut automatisch, wodurch der HTML-Code wartungsfreundlicher wird. Nun, solange form hat die Klasse putImages, alles andere wird automatisch erledigt. Das heißt, die input muss keinen besonderen Namen haben.
  2. Das Array-Format, das normales HTML übermittelt, wird von JavaScript in der data.append-Zeile neu erstellt. Beachten Sie die Klammern.

Mit diesen Änderungen erzeugt das Senden mit JavaScript jetzt genau dasselbe $_FILES Array als Übermittlung mit einfachem HTML.

1646125868 144 Multipartformdata mit jQueryajax senden
evandro777

Ich habe diese Funktion nur basierend auf einigen Informationen erstellt, die ich gelesen habe.

Verwenden Sie es wie mit .serialize()stattdessen einfach setzen .serializefiles();.
Arbeite hier in meinen Tests.

//USAGE: $("#form").serializefiles();
(function($) {
$.fn.serializefiles = function() {
    var obj = $(this);
    /* ADD FILE TO PARAM AJAX */
    var formData = new FormData();
    $.each($(obj).find("input[type="file"]"), function(i, tag) {
        $.each($(tag)[0].files, function(i, file) {
            formData.append(tag.name, file);
        });
    });
    var params = $(obj).serializeArray();
    $.each(params, function (i, val) {
        formData.append(val.name, val.value);
    });
    return formData;
};
})(jQuery);

Wenn Ihr Formular in Ihrem HTML definiert ist, ist es einfacher, das Formular an den Konstruktor zu übergeben, als es zu iterieren und Bilder hinzuzufügen.

$('#my-form').submit( function(e) {
    e.preventDefault();

    var data = new FormData(this); // <-- 'this' is your form element

    $.ajax({
            url: '/my_URL/',
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',     
            success: function(data){
            ...

1646125869 138 Multipartformdata mit jQueryajax senden
Gemeinschaft

Die Antwort von Devin Venable entsprach fast meinen Vorstellungen, aber ich wollte eine, die auf mehreren Formularen funktioniert und die bereits im Formular angegebene Aktion verwendet, damit jede Datei an die richtige Stelle gelangt.

Ich wollte auch die on()-Methode von jQuery verwenden, damit ich die Verwendung von .ready() vermeiden konnte.

Das hat mich dazu gebracht: (formSelector durch Ihren jQuery-Selektor ersetzen)

$(document).on('submit', formSelecter, function( e ) {
        e.preventDefault();
    $.ajax( {
        url: $(this).attr('action'),
        type: 'POST',
        data: new FormData( this ),
        processData: false,
        contentType: false
    }).done(function( data ) {
        //do stuff with the data you got back.
    });

});

Wenn die Dateieingabe name gibt ein Array und Flags an multipleund Sie analysieren das Ganze form mit FormDataist es nicht notwendig, iterativ zu sein append() die Eingabedateien. FormData verarbeitet automatisch mehrere Dateien.

$('#submit_1').on('click', function() {
  let data = new FormData($("#my_form")[0]);

  $.ajax({
    url: '/path/to/php_file',
    type: 'POST',
    data: data,
    processData: false,
    contentType: false,
    success: function(r) {
      console.log('success', r);
    },
    error: function(r) {
      console.log('error', r);
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="my_form">
  <input type="file" name="multi_img_file[]" id="multi_img_file" accept=".gif,.jpg,.jpeg,.png,.svg" multiple="multiple" />
  <button type="button" name="submit_1" id="submit_1">Not type="submit"</button>
</form>

Beachten Sie, dass eine regelmäßige button type="button" verwendet wird, nicht type="submit". Dies zeigt, dass keine Abhängigkeit von der Verwendung besteht submit um diese Funktion zu erhalten.

Das Ergebnis $_FILES Der Eintrag in den Chrome-Entwicklertools sieht folgendermaßen aus:

multi_img_file:
  error: (2) [0, 0]
  name: (2) ["pic1.jpg", "pic2.jpg"]
  size: (2) [1978036, 2446180]
  tmp_name: (2) ["/tmp/phphnrdPz", "/tmp/phpBrGSZN"]
  type: (2) ["image/jpeg", "image/jpeg"]

Hinweis: Es gibt Fälle, in denen einige Bilder gut hochgeladen werden, wenn sie als einzelne Datei hochgeladen werden, aber sie schlagen fehl, wenn sie in einer Gruppe von mehreren Dateien hochgeladen werden. Das Symptom ist, dass PHP leer meldet $_POST und $_FILES ohne dass AJAX irgendwelche Fehler auslöst. Das Problem tritt bei Chrome 75.0.3770.100 und PHP 7.0 auf. Scheint nur bei 1 von mehreren Dutzend Bildern in meinem Testset zu passieren.

899000cookie-checkMultipart/formdata mit jQuery.ajax senden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy