Pytanie Jak mogę przesłać pliki asynchronicznie?


Chciałbym przesłać plik asynchronicznie z jQuery. To jest mój HTML:

<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

A tutaj moje Jquery kod:

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});

Zamiast przesyłanego pliku, otrzymuję tylko nazwę pliku. Co mogę zrobić, aby rozwiązać ten problem?

Obecne rozwiązanie

Używam jQuery Form Plugin do przesyłania plików.


2609
2017-10-03 10:22


pochodzenie


dostajesz tylko nazwę pliku, ponieważ twoja nazwa pliku var otrzymuje wartość $ ("# file"), a nie plik, który leży na wejściu - Jimmy
Oto dobry: http://blueimp.github.io/jQuery-File-Upload/ - Ładowanie HTML5 ajax - Wdzięczne przejście do iframe dla nieobsługiwanych przeglądarek - Przesyłanie plików asynchronicznych z wieloma plikami Zużyliśmy go i działa świetnie. (Dokumentacja tutaj) - Ashish Panery
jQuery Form Plugin wydaje się najbardziej prostym w obsłudze i kompatybilnym z różnymi przeglądarkami ... mam rację? - Lyth
Sprawdź także: stackoverflow.com/questions/6974684/..., tutaj wyjaśnia, jak osiągnąć to poprzez jQuery - Chococroc
@ Jimmy Skąd wziąłby plik zawierający dane wejściowe? - alex


Odpowiedzi:


Z HTML5 możesz przesyłać pliki za pomocą Ajax i jQuery. Możliwa jest także weryfikacja plików (nazwa, rozmiar i typ MIME) lub obsługa zdarzenia postępu za pomocą znacznika postępu HTML5 (lub elementu div). Ostatnio musiałem utworzyć narzędzie do przesyłania plików, ale nie chciałem go używać Lampa błyskowa ani iframe lub wtyczek, a po pewnych badaniach wymyśliłem rozwiązanie.

HTML:

<form enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>
<progress></progress>

Po pierwsze, możesz wykonać jakąś walidację, jeśli chcesz. Na przykład w zdarzeniu onChange pliku:

$(':file').on('change', function() {
    var file = this.files[0];
    if (file.size > 1024) {
        alert('max upload size is 1k')
    }

    // Also see .name, .type
});

Teraz Ajax przesyłaj za pomocą kliknięcia przycisku:

$(':button').on('click', function() {
    $.ajax({
        // Your server script to process the upload
        url: 'upload.php',
        type: 'POST',

        // Form data
        data: new FormData($('form')[0]),

        // Tell jQuery not to process data or worry about content-type
        // You *must* include these options!
        cache: false,
        contentType: false,
        processData: false,

        // Custom XMLHttpRequest
        xhr: function() {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) {
                // For handling the progress of the upload
                myXhr.upload.addEventListener('progress', function(e) {
                    if (e.lengthComputable) {
                        $('progress').attr({
                            value: e.loaded,
                            max: e.total,
                        });
                    }
                } , false);
            }
            return myXhr;
        }
    });
});

Jak widać, dzięki HTML5 (i niektórym badaniom) przesyłanie plików staje się nie tylko możliwe, ale i bardzo łatwe. Wypróbuj to Google Chrome ponieważ niektóre składniki HTML5 przykładów nie są dostępne w każdej przeglądarce.


2336
2018-01-06 13:34



Czy mogę następnie użyć $ _FILES w upload.php? - Alessandro Cosentino
To powinno działać w Internet Explorerze, ale tylko w wersji 10. (caniuse.com/xhr2) - Samir
Nie działa w IE7-9 - KevinDeus
Cześć, doceniam PHP jest twoim językiem wyboru ... ale zastanawiam się czy wiesz, czy to też działa w ASP.NET MVC? Jestem programistą .NET i próbowałem wykorzystać Twój prosty przykład do przesyłania niektórych plików AJAX, ale po stronie serwera nie dostaję pliku opublikowanego przez AJAX. Korzystam z najnowszego Chrome. - Shumii
Jego Tworzyć dane kto tu robi całą magię. Koniecznie sprawdź te dokumenty - zawiera ono wszystkie pytania dotyczące wielu plików i pól. - incarnate


Istnieje wiele gotowych wtyczek do przesyłania plików dla jQuery.

Robienie tego typu hackowania nie jest przyjemnym doświadczeniem, więc ludzie lubią używać gotowych rozwiązań.

Oto kilka:

Możesz wyszukać więcej projektów na NPM (używając "jquery-plugin" jako słowa kluczowego) lub na Github.


335
2017-10-15 10:35



Link AjaxFUP wydaje się być uszkodzony. Podejrzewam, że to jest to, o czym mowa: valums.com/ajax-upload - UlfR
Dla jeszcze jednej wtyczki do odczytu, zawsze jest Filepicker.io, co jest miłe w tym, że zajmuje się wszystkimi nieprzyjemnymi problemami z obsługą dużych plików itp. - brettcvz
To właściwie tylko około 10 linii waniliowego JS. To naprawdę nie jest takie złe. - mpen
Gotowe wtyczki do rozwiązań mogą działać świetnie, ale nie pomaga po jakimś czasie, gdy odkryjesz, że to nie działa, myślałeś, że to zrobisz i musiałeś zhakować to z nieznanymi skryptami. Więc idzie w obie strony. - fletchsod
Mogę uzyć JQuery File Uploader w przypadku wielu filmów ..? czy to będzie wspierać? - Mr world wide


Aktualizacja 2017: wciąż zależy od przeglądarek Twój zastosowania demograficzne.

Ważna rzecz do zrozumienia dzięki "nowemu" HTML5 file API to znaczy nie był obsługiwany przed IE 10. Jeśli określony rynek, na który kierujesz, ma wyższą niż przeciętną skłonność do starszych wersji systemu Windows, możesz nie mieć do niego dostępu.

W roku 2017 około 5% przeglądarek to jedne z IE 6, 7, 8 lub 9. Jeśli trafisz do dużej korporacji (np. Jest to narzędzie B2B lub coś, co dostarczasz na szkolenia), liczba ta może wzrosnąć. Jeszcze kilka miesięcy temu - w 2016 roku - zajmowałem się firmą wykorzystującą IE8 na ponad 60% swoich maszyn.

Zanim zrobisz cokolwiek: sprawdź, która przeglądarka Twój użytkownicy korzystają. Jeśli tego nie zrobisz, nauczysz się szybkiej i bolesnej lekcji, dlaczego "działa dla mnie" nie jest wystarczająco dobra w dostarczeniu klientowi.

Moja odpowiedź z 2008 roku jest następująca.


Istnieją jednak metody przesyłania plików, które nie są oparte na JS. Możesz utworzyć element iframe na stronie (ukryty za pomocą CSS), a następnie kierować swój formularz, by publikować w tym elemencie iframe. Strona główna nie musi się poruszać.

Jest to "prawdziwy" post, więc nie jest w pełni interaktywny. Jeśli potrzebujesz statusu, potrzebujesz czegoś po stronie serwera, aby to przetworzyć. Różni się to znacznie w zależności od serwera. ASP.NET ma ładniejsze mechanizmy. PHP plain zawiedzie, ale możesz go użyć Perl lub modyfikacje Apache, aby ominąć to.

Jeśli potrzebujesz wielu plików do przesłania, najlepiej zrobić każdy z nich po jednym na raz (aby pokonać maksymalne limity wysyłania plików). Opublikuj pierwszy formularz w elemencie iframe, monitoruj jego postępy, używając powyższego i po zakończeniu, opublikuj drugi formularz w elemencie iframe i tak dalej.

Lub użyj rozwiązania Java / Flash. Są bardziej elastyczni w tym, co mogą zrobić ze swoimi wpisami ...


237
2017-10-03 10:41



Dla rekordu możliwe jest teraz przesyłanie czystych plików AJAX, jeśli przeglądarka obsługuje File API - developer.mozilla.org/en/using_files_from_web_applications - meleyal
Chyba że potrzebujesz wsparcia IE9. caniuse.com/fileapi - Oli
Rozwiązanie iframe jest dość proste i łatwe w obsłudze - Matthew Lock
jest to dość stara odpowiedź, ale było to trochę mylące. IE wspierał XHR natywnie od IE7 i wspierał go przez ActiveX aż do IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp. Praktycznym sposobem na to było na pewno skierowanie elementów flash (shockwave) lub uruchomienie formantu Flash / ActiveX (Silverlight). Jeśli możesz utworzyć żądanie i obsłużyć odpowiedź za pośrednictwem javascript, to jest to ajax .. chociaż, mówiąc o tym, ajax jest synonimem xhr, ale sam nie opisuje mechanizmu podkreślenia / komponentów, które dostarcza / wymienia ładunek. - Brett Caswell
@BrettCaswell Nie mówiłem, że AJAX / XHR nie były możliwe, tylko, że nie można było z nimi opublikować starych, ale już istniejących wersji IE. To było i pozostaje całkowicie prawdziwe. - Oli


Polecam używanie Fine Uploader wtyczka do tego celu. Twój JavaScript kod byłby:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});

105
2017-11-21 16:38



Używa JSON - więc dla starej wersji PHP będzie to niemożliwe. - Lorenzo Manucci
Wydaje się znacznie czystsze niż przesyłanie plików Ajax, gdzie muszę dołączyć ogromny kawałek kodu, aby użyć tego cholerstwa. - ripper234
URL jest teraz valums.com/ajax-upload. - Patrick Fisher
"Ta wtyczka jest dostępna na zasadach GNU GPL 2 lub nowszej wersji oraz GNU LGPL 2 lub nowszego." Tak długo, jak nie rozpowszechniasz kopii lub zmodyfikowanej wersji, nie musisz otwierać projektu. - Trantor Liu
To jest strona internetowa (fineuploader.com) Znalazłem, to V4.2. - Andrew_1510


Uwaga: ta odpowiedź jest nieaktualna, możliwe jest teraz przesyłanie plików za pomocą XHR.


Nie możesz przesyłać plików za pomocą XMLHttpRequest (Ajax). Możesz symulować efekt za pomocą elementu iframe lub Flasha. Doskonały jQuery Form Plugin które publikuje twoje pliki przez element iframe, aby uzyskać efekt.


87
2017-10-03 10:36



Tak, możesz POST na element iframe i przechwycić tam plik. Mam bardzo ograniczone doświadczenie z tym, więc nie mogę tego naprawdę skomentować. - Mattias
Mała uwaga: w najnowszych wersjach chrome i firefox jest to możliwe, stackoverflow.com/questions/4856917/... - Alleo


To Plik AJAX przesyłaj wtyczkę jQuery wczytuje plik i przekazuje plik odpowiedź na wywołanie zwrotne, nic więcej.

  • Nie zależy od konkretnego kodu HTML, wystarczy go podać <input type="file">
  • Nie wymaga od twojego serwera odpowiedzi w żaden szczególny sposób
  • Nie ma znaczenia, ile plików używasz, ani gdzie są na stronie

- Używaj tak mało jak -

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

- lub tak samo jak -

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});

81
2017-07-29 00:34



Nie działa z 1.9.1: | - user840250
@ user840250 jQuery 1.9.1? - Jordan Feldstein


Opakowanie dla przyszłych czytelników.

Przesyłanie plików asynchronicznych

Z HTML5

Możesz przesyłać pliki z jQuery używając $.ajax() metoda jeśli Tworzyć dane i Interfejs API pliku są obsługiwane (obie funkcje HTML5).

Możesz także wysyłać pliki bez FormData ale tak czy inaczej plik API musi być obecny, aby przetwarzać pliki w taki sposób, aby można je było wysłać XMLHttpRequest (Ajax).

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Szybki, czysty JavaScript (bez jQuery) przykład zobacz "Przesyłanie plików przy użyciu obiektu FormData".

Fallback

Gdy HTML5 nie jest obsługiwany (nie Interfejs API pliku) jedynym innym czystym rozwiązaniem JavaScript (nr Lampa błyskowa lub jakiejkolwiek innej wtyczki przeglądarki) ukryta ramka iframe technika, która pozwala emulować asynchroniczne żądanie bez użycia XMLHttpRequest obiekt.

Polega na ustawieniu elementu iframe jako celu formularza przy użyciu danych wejściowych pliku. Kiedy użytkownik przesyła żądanie, a pliki są przesyłane, ale odpowiedź jest wyświetlana wewnątrz elementu iframe zamiast ponownego renderowania strony głównej. Ukrywanie elementu iframe powoduje, że cały proces staje się przezroczysty dla użytkownika i emuluje żądanie asynchroniczne.

Jeśli zrobi się to poprawnie, powinno działać praktycznie w dowolnej przeglądarce, ale ma pewne zastrzeżenia, jak uzyskać odpowiedź od elementu iframe.

W takim przypadku możesz użyć wtyczki takiej jak Bifröst który używa technika iframe ale zapewnia również Transport Ajax jQuery pozwalając Wyślij pliki tylko z $.ajax() metoda taka jak ta:

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Wtyczki

Bifröst to tylko małe opakowanie, które dodaje wsparcie zastępcze do metody ajax jQuery, ale wiele z wyżej wymienionych wtyczek takich jak jQuery Form Pluginlub Przesyłanie plików jQuery obejmują cały stos od HTML5 do różnych fallbacks i kilka przydatnych funkcji, aby ułatwić proces. W zależności od twoich potrzeb i wymagań możesz rozważyć samodzielną implementację lub jedną z tych wtyczek.


75
2017-08-25 14:17



Na podstawie dokumentacji należy pamiętać, że należy również wysłać contentType: false. Kiedy nie wysłałem tego przy użyciu chrome, typ zawartości formularza został unieważniony przez jQuery. - ash
Niezła odpowiedź. Kilka propozycji ulepszeń: Usuń części kodu niezwiązane z odpowiedzią, na przykład .done() i .fail() callbacks. Również przykład bez użycia FormData a lista pro / cons byłaby niesamowita. - Zero3
Mam ten błąd: TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement. - candlejack


Użyłem poniższego skryptu, aby przesłać obrazy, które działają dobrze.

HTML

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    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];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

Wyjaśnienie

Używam odpowiedzi div aby pokazać animację przesyłania i odpowiedź po zakończeniu przesyłania.

Najlepsze jest to, że możesz przesłać dodatkowe dane, takie jak identyfikatory i itp. Z plikiem, gdy używasz tego skryptu. Wspominam o tym extra-data jak w scenariuszu.

Na poziomie PHP będzie to działać jak normalne przesyłanie plików. dodatkowe dane można pobrać jako $_POST dane.

Tutaj nie używasz wtyczki i innych rzeczy. Możesz zmienić kod, jak chcesz. Nie ślepo tu kodujesz. Jest to podstawowa funkcjonalność przesyłania dowolnego pliku jQuery. Właściwie JavaScript.


57
2018-01-25 11:03



-1 dla używania jQuery i nie używania jego mechanizmu wyboru i obsługi zdarzeń. addEventListener nie jest w wielu przeglądarkach. - Mark
Ponieważ nie ma sensu dodawać oddzielnej odpowiedzi, która byłaby w większości oparta na tym jednym, z kilkoma zmianami. Zamiast tego, ta odpowiedź powinna zostać poprawiona. - Mark
@RainFromHeaven, proszę, możesz edytować odpowiedź? Nie wiem, jak to zrobić w sposób między przeglądarkami. - Thiago Negri
Nadal nie działa w IE 9 iw dół. Wiele użytkowników nadal korzysta z tych wersji IE. - Pierre
Czy ktoś może wyjaśnić, w jaki sposób można to zrobić do pracy w asp.net? Czy używam webmethod? Jeśli tak, jak by to wyglądało? - Arbaaz


Natknąłem się na kilka naprawdę potężnych bibliotek do przesyłania plików opartych na jQuery. Sprawdź te:

  1. Plupload
  2. Przesyłanie plików jQuery
  3. FineUploader

55
2018-04-08 16:43





Możesz przesłać po prostu za pomocą jQuery .ajax().

HTML:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

CSS

.progress { display: none; }

JavaScript:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});

42
2017-08-08 02:59



dziękuję, to jest praca nad plikami .xls - Tarek Kalaji
Jakiej biblioteki jQuery potrzebuję do uruchomienia tego kodu? - Rayden Black
@RaydenBlack tylko jQuery. - Zayn Ali
jak uzyskać postęp w zakresie przesyłania? - Ali Sherafat
@AliSherafat zaktualizowałem swoją odpowiedź. Spróbuj - Zayn Ali


Możesz to zrobić w JavaScript JavaScript bardzo łatwo. Oto fragment z mojego obecnego projektu:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);

40
2018-02-17 09:34



@Gary: Przepraszam, też powinienem opublikować. Właśnie używałem nowej funkcji przeciągania i upuszczania w HTML5; możesz znaleźć przykład tutaj: html5demos.com/file-api#view-source - po prostu kliknij "wyświetl źródło". Zasadniczo w środku ondrop wydarzenie, które możesz zrobić var file = e.dataTransfer.files[0] - mpen
Być może pytanie zostało zmienione od tamtego czasu, ale niektórzy ludzie w otwartej dyskusji, którą otwieram, uważają, że odpowiedź JS vanilla jest wyłączona, jeśli OP prosi o rozwiązanie jQuery (o ile takie istnieje) i takie odpowiedzi należą do osobnego pytania. - Andy
@Andy Cóż, nie zgadzam się i wydaje się, że 34 inne też. Jeśli możesz użyć jQuery, możesz oczywiście użyć JavaScript. W każdym razie jest to strona społecznościowa - nie tylko OP, próbuję tu pomóc. Każdy może wybrać lub użyć odpowiedzi, którą lubi najbardziej. Niektórzy ludzie po prostu skłaniają się ku jQuery, ponieważ sądzą, że będzie to o wiele łatwiejsze / mniej linii kodu, kiedy naprawdę nie będą potrzebować dodatkowego ekwipunku. - mpen