Jak mogę przesyłać pliki asynchronicznie?

2914

Chciałbym przesłać plik asynchronicznie z jQuery.

$(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: ");
            }
        });
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

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

Sergio del Amo
źródło
Istnieją różne gotowe wtyczki do wysyłania plików dla jQuery. Robienie tego typu przesyłania hacków nie jest przyjemnością, więc ludzie lubią korzystać z gotowych rozwiązań. Oto kilka z nich: - jQuery File Uploader - Multiple File Upload Plugin - Mini Multiple File Upload - jQuery File Upload Można szukać większej liczby projektów na NPM (przy użyciu jQuery plugin "" jako słowa kluczowego) lub na Github.
Wesoły
72
otrzymujesz tylko nazwę pliku, ponieważ twoja nazwa pliku var otrzymuje wartość $ ('# file'), a nie plik, który znajduje się na wejściu
Jimmy
21
Oto dobry: http://blueimp.github.io/jQuery-File-Upload/ - Przesyłanie ajax HTML5 - Wdzięczny powrót do ramek iframe dla nieobsługiwanych przeglądarek - Przesyłanie asynchroniczne z wieloma plikami Użyliśmy go i działa świetnie. ( Dokumentacja tutaj )
Ashish Panery
3
Zobacz także: stackoverflow.com/questions/6974684/… , tutaj wyjaśniono, jak to osiągnąć za pomocą jQuery
Chococroc
2
@Jimmy Skąd miałby dostać plik, który znajduje się w danych wejściowych?
alex

Odpowiedzi:

2519

Za pomocą HTML5 możesz przesyłać pliki za pomocą Ajax i jQuery. Ponadto możesz sprawdzać poprawność plików (nazwa, rozmiar i typ MIME) lub obsługiwać zdarzenie progress za pomocą znacznika postępu HTML5 (lub div). Ostatnio musiałem utworzyć program do przesyłania plików, ale nie chciałem używać Flasha, iframe ani wtyczek i po kilku 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 przeprowadzić walidację, jeśli chcesz. Na przykład w .on('change')przypadku 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()prześlij 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 jest nie tylko możliwe, ale bardzo łatwe. Wypróbuj go z Google Chrome, ponieważ niektóre składniki HTML5 przykładów nie są dostępne w każdej przeglądarce.

olanod
źródło
14
Czy mogę wtedy użyć $ _FILES w pliku upload.php?
Alessandro Cosentino,
71
Powinno to działać w przeglądarce Internet Explorer, ale tylko w wersji 10. ( caniuse.com/xhr2 )
Tyler,
18
Cześć, doceniam, że PHP jest twoim wybranym językiem ... ale zastanawiam się, czy wiesz, czy to również działa w ASP.NET MVC? Jestem programistą .NET i próbowałem wykorzystać twój prosty przykład do przesłania niektórych plików AJAX, ale po stronie serwera nie otrzymałem pliku, który opublikowałem przez AJAX. Używam najnowszego Chrome.
Shumii
25
To FormData który wykonuje całą magię tutaj. Pamiętaj, aby sprawdzić te dokumenty - obejmuje wszystkie pytania dotyczące wielu plików i pól.
wcielono
4
Tylko żeby ktoś inny nie spędzał godzin ... name="file"jest to bardzo ważne na <input>znaczniku pliku, jeśli zamierzasz używać danych w PHP (i prawdopodobnie w innych miejscach). Formularz utworzyłem dynamicznie za pomocą javascript, więc nie potrzebowałem atrybutu name, ale dowiedziałem się, jak bardzo potrzebujesz go do odzyskania danych po stronie serwera.
Kivak Wolf,
273

Aktualizacja 2019: Nadal zależy od przeglądarek, z których korzysta Twoja grupa demograficzna.

Ważną rzeczą do zrozumienia z „nowym” fileAPI HTML5 jest to, że nie był obsługiwany aż do IE 10 . Jeśli konkretny rynek, na który chcesz dążyć, ma ponadprzeciętną skłonność do starszych wersji systemu Windows, możesz nie mieć do niego dostępu.

Od 2017 r. Około 5% przeglądarek to przeglądarki IE 6, 7, 8 lub 9. Jeśli kierujesz się do dużej korporacji (np. Jest to narzędzie B2B lub coś, co dostarczasz na szkolenie), liczba ta może gwałtownie wzrosnąć . W 2016 roku miałem do czynienia z firmą używającą IE8 na ponad 60% swoich maszyn.

Od tej edycji jest rok 2019, prawie 11 lat po mojej pierwszej odpowiedzi. IE9 i niższe są na całym świecie około 1%, ale wciąż istnieją klastry o wyższym użyciu.

Ważną zaletą - niezależnie od funkcji - jest sprawdzenie, jakiej przeglądarki używają Twoi użytkownicy . Jeśli tego nie zrobisz, nauczysz się szybkiej i bolesnej lekcji na temat tego, dlaczego „praca dla mnie” nie jest wystarczająco dobra w dostawie do klienta. caniuse to przydatne narzędzie, ale pamiętaj, skąd biorą dane demograficzne. Mogą nie pasować do twojego. To nigdy nie jest prawdziwsze niż środowiska korporacyjne.

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


Istnieją jednak realne metody przesyłania plików inne niż JS. Możesz utworzyć ramkę iframe na stronie (którą ukrywasz za pomocą CSS), a następnie skierować formularz do opublikowania w tej ramce iframe. Strona główna nie musi się poruszać.

To „prawdziwy” post, więc nie jest całkowicie 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. Zwykły PHP zawiedzie, ale można go obejść za pomocą modyfikacji Perla lub Apache.

Jeśli potrzebujesz wielu plików do przesłania, najlepiej zrobić każdy plik pojedynczo (aby przekroczyć maksymalne limity przesyłania plików). Opublikuj pierwszy formularz w ramce iframe, monitoruj jego postęp, korzystając z powyższego, a po jego zakończeniu opublikuj drugi formularz w ramce iframe i tak dalej.

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

Oli
źródło
142
Dla
przypomnienia
Rozwiązanie iframe jest dość proste i łatwe do uruchomienia
Matthew Lock
jest to dość stara odpowiedź, ale była nieco myląca. IE obsługiwał XHR natywnie już w IE7 i wspierał go przez ActiveX już w IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp . Praktycznym sposobem na to było z pewnością ukierunkowanie na komponenty Flash (fala uderzeniowa) lub wprowadzenie kontrolki Flash / ActiveX (Silverlight). Jeśli możesz zainicjować żądanie i obsłużyć odpowiedź za pomocą javascript, to jest to ajax .. powiedząc jednak, że ajax jest synonimem xhr, ale sam nie opisuje mechanizmu podkreślania / komponentów, które dostarczają / wymieniają ładunek.
Brett Caswell
4
@BrettCaswell Nie mówiłem, że AJAX / XHR nie jest możliwe, tylko że nie było możliwe opublikowanie pliku w starych, ale wciąż żywych wersjach IE. To było i pozostaje całkowicie prawdziwe.
Oli,
To nie jest tak, to jest opinia UX - być może ważna.
Nimjox
112

W tym celu polecam użycie wtyczki Fine Uploader . Twój JavaScriptkod to:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});
Shiladitya
źródło
Używa JSON - więc dla starej wersji PHP nie będzie to moż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,
Nowszy adres URL dla wersji 2 to teraz valums-file-uploader.github.com/file-uploader
Simon East
35
„Ta wtyczka jest dostępna na licencji GNU GPL 2 lub nowszej i GNU LGPL 2 lub nowszej.” Tak długo, jak nie rozpowszechniasz kopii ani zmodyfikowanej wersji, nie musisz otwierać swojego projektu.
Trantor Liu,
Czy coś brakuje? Wydaje się, że ta biblioteka nie używa jquery, więc nie obsługuje składni z odpowiedzi?
James McCormack
102

Uwaga: ta odpowiedź jest nieaktualna, teraz można przesyłać pliki za pomocą XHR.


Nie można przesyłać plików za pomocą XMLHttpRequest (Ajax). Możesz symulować efekt za pomocą elementu iframe lub Flash. Doskonała wtyczka jQuery Form, która publikuje twoje pliki poprzez ramkę iframe, aby uzyskać efekt.

Mattias
źródło
1
Tak, możesz wysłać test POST do elementu iframe i przechwycić tam plik. Mam jednak bardzo ograniczone doświadczenie, więc nie mogę tego komentować.
Mattias
15
Mała uwaga: w najnowszych wersjach chrome i firefox jest to możliwe, stackoverflow.com/questions/4856917/…
Alleo,
Nieobsługiwany w IE9 i mniej
Radmation
96

Podsumowanie dla przyszłych czytelników.

Asynchroniczne przesyłanie plików

Z HTML5

Możesz przesyłać pliki za pomocą jQuery przy użyciu $.ajax()metody, jeśli FormData i interfejs API plików są obsługiwane (obie funkcje HTML5).

Możesz również wysyłać pliki bez FormData, ale w obu przypadkach interfejs API plików musi być obecny, aby przetwarzać pliki w taki sposób, aby można je było przesłać za pomocą 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!");
});

Przykład szybkiego, czystego kodu JavaScript ( bez jQuery ) zawiera sekcja „ Wysyłanie plików przy użyciu obiektu FormData ”.

Fallback

Gdy HTML5 nie jest obsługiwane (bez interfejsu API plików ), jedynym innym czystym rozwiązaniem JavaScript (bez Flasha ani żadnej innej wtyczki do przeglądarki) jest technika ukrytego iframe , która pozwala emulować asynchroniczne żądanie bez użycia obiektu XMLHttpRequest .

Polega na ustawieniu elementu iframe jako celu formularza za pomocą danych wejściowych pliku. Gdy użytkownik przesyła żądanie, przesyłane są pliki, ale pliki są przesyłane, ale odpowiedź jest wyświetlana w ramce iframe zamiast ponownego renderowania strony głównej. Ukrywanie elementu iframe sprawia, że ​​cały proces jest przezroczysty dla użytkownika i emuluje żądanie asynchroniczne.

Prawidłowo wykonane powinno działać praktycznie w każdej przeglądarce, ale ma pewne zastrzeżenia, jak uzyskać odpowiedź z iframe.

W takim przypadku możesz użyć wtyczki otoki, takiej jak Bifröst, która wykorzystuje technikę iframe, ale zapewnia także transport Ajax jQuery pozwalający na wysyłanie plików za pomocą tylko takiej $.ajax()metody:

$.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 obsługę rezerwową do metody ajax jQuery'ego, ale wiele z wyżej wymienionych wtyczek, takich jak jQuery Form Plugin lub jQuery File Upload, zawiera cały stos od HTML5 do różnych kopii zapasowych oraz kilka przydatnych funkcji ułatwiających ten proces. W zależności od potrzeb i wymagań możesz rozważyć implementację lub dowolną z tych wtyczek.

404
źródło
3
Należy zwrócić uwagę na jedną dokumentację: należy również wysłać contentType: false. Kiedy nie wysłałem tego z chrome, typ zawartości formularza został unieważniony przez jQuery.
popiół
Niezła odpowiedź. Kilka sugestii dotyczących ulepszeń: Usuń części kodu niezwiązane z odpowiedzią, na przykład .done()i .fail()wywołania zwrotne. Również przykład bez użycia FormDatai lista zalet / wad byłby niesamowity.
Zero3,
TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
Wystąpił
85

Ta wtyczka jQuery przesyłająca plik AJAX przesyła plik gdzieś i przekazuje odpowiedź na wywołanie zwrotne, nic więcej.

  • To nie zależy od konkretnego HTML, po prostu daj mu <input type="file">
  • Nie wymaga od twojego serwera żadnej reakcji
  • Nie ma znaczenia, ile plików używasz ani gdzie znajdują się na stronie

- Używaj tak mało jak -

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

- lub tyle co -

$('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');
  }
});
Jordan Feldstein
źródło
1
@ user840250 jQuery 1.9.1?
Jordan Feldstein,
62

Korzystam z poniższego skryptu, aby przesył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

Korzystam z odpowiedzi, divaby wyświetlić animację przesyłania i odpowiedzi 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. Wspomniałem o tym extra-datajak w skrypcie.

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

Tutaj nie używasz wtyczki i innych rzeczy. Możesz zmienić kod, jak chcesz. Nie kodujesz na ślepo tutaj. Jest to podstawowa funkcjonalność każdego przesyłania plików jQuery. Właściwie JavaScript.

Techie
źródło
5
-1 za używanie jQuery i nieużywanie jego mechanizmu wyboru i procedur obsługi zdarzeń. addEventListenernie jest przeglądarką.
Mark
3
Ponieważ bezcelowe byłoby dodawanie osobnej odpowiedzi, która byłaby w większości oparta na tej, z kilkoma zmianami. Zamiast tego należy poprawić tę odpowiedź.
Mark
2
@RainFromHeaven, proszę, możesz edytować odpowiedź? Nie wiem, jak to zrobić w przeglądarce.
Thiago Negri
2
Nadal nie działa w IE 9 i starszych. Przydział użytkowników nadal korzysta z tych wersji IE.
Pierre
1
Czy ktoś może wyjaśnić, w jaki sposób można to zrobić w asp.net? Czy używam metody internetowej? Jeśli tak, jak by to wyglądało?
SamuraiJack
49

Możesz to zrobić w waniliowym JavaScript z łatwością. Oto fragment 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);
mpen
źródło
3
@Gary: Przepraszam, ja też powinienem był to zamieścić. Właśnie korzystałem z nowej funkcji przeciągania i upuszczania w HTML5; przykład możesz znaleźć tutaj: html5demos.com/file-api#view-source - po prostu kliknij „wyświetl źródło”. Zasadniczo w ondropwydarzeniu możesz to zrobićvar file = e.dataTransfer.files[0]
otwórz
Być może pytanie zostało zredagowane od tego czasu, ale niektórzy ludzie w dyskusji, którą otworzyłem, myślę, że waniliowa odpowiedź JS jest nie na temat, jeśli OP poprosi o rozwiązanie jQuery (pod warunkiem, że istnieje) i takie odpowiedzi należą do osobnego pytania.
Andy
4
@ Andy No cóż, nie zgadzam się i wydaje się, że 34 innych też. Jeśli możesz użyć jQuery, z pewnością możesz użyć JavaScript. W każdym razie jest to strona społecznościowa - nie tylko OP próbuję tutaj pomóc. Każdy może wybrać / użyć odpowiedzi, którą najbardziej lubi. Niektórzy ludzie po prostu skłaniają się ku jQuery, ponieważ uważają, że będzie to o wiele łatwiejsze / mniej linii kodu, kiedy tak naprawdę nie będą w ogóle potrzebować dodatkowej biblioteki.
mpen
47

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) {
                // ...
            }
       });
    }));
});
Zayn Ali
źródło
1
@RaydenBlack tylko jQuery.
Zayn Ali,
jak uzyskać postęp przesyłania?
Ali Sherafat
44

Najprostszym i najbardziej niezawodnym sposobem, w jaki to zrobiłem w przeszłości, jest po prostu celowanie w ukryty znacznik iFrame za pomocą formularza - następnie zostanie on przesłany w elemencie iframe bez ponownego ładowania strony.

To znaczy, jeśli nie chcesz używać wtyczki, JavaScript ani innych form „magii” innych niż HTML. Oczywiście możesz to połączyć z JavaScriptem lub czym ...

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

Możesz także przeczytać zawartość ramki iframe pod onLoadkątem błędów serwera lub odpowiedzi na sukces, a następnie przekazać ją użytkownikowi.

Chrome, iFrames i onLoad

-Uwaga- musisz czytać dalej, jeśli jesteś zainteresowany tym, jak skonfigurować blokadę interfejsu użytkownika podczas przesyłania / pobierania

Obecnie Chrome nie wyzwala zdarzenia onLoad dla elementu iframe, gdy jest on używany do przesyłania plików. Firefox, IE i Edge wszystkie uruchamiają zdarzenie onload podczas przesyłania plików.

Jedyne rozwiązanie, które znalazłem, działa w przeglądarce Chrome, to użycie pliku cookie.

Aby to zrobić w zasadzie po uruchomieniu przesyłania / pobierania:

  • [Po stronie klienta] Rozpocznij interwał, aby sprawdzić istnienie pliku cookie
  • [Po stronie serwera] Rób co chcesz z danymi pliku
  • [Po stronie serwera] Ustaw plik cookie dla interwału po stronie klienta
  • [Po stronie klienta] Interwał widzi ciasteczko i wykorzystuje je jak zdarzenie onLoad. Na przykład możesz uruchomić blokadę interfejsu użytkownika, a następnie onLoad (lub po utworzeniu pliku cookie) usuwasz blokadę interfejsu użytkownika.

Używanie do tego pliku cookie jest brzydkie, ale działa.

Zrobiłem wtyczkę jQuery, aby poradzić sobie z tym problemem dla Chrome podczas pobierania, znajdziesz tutaj

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js

Ta sama podstawowa zasada dotyczy również przesyłania.

Aby użyć downloadera (oczywiście JS)

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

A po stronie serwera, tuż przed przesłaniem danych pliku, utwórz ciasteczko

 setcookie('iDownloader', true, time() + 30, "/");

Wtyczka zobaczy plik cookie, a następnie wyzwoli połączenie onCompletezwrotne.

Artystyczny Feniks
źródło
3
Kocham to. Gdyby tylko ktoś mógł wspomnieć o potencjalnych problemach z tym genialnym rozwiązaniem. Naprawdę nie rozumiem, dlaczego ludzie piszą i używają tych niezgrabnych bibliotek i wtyczek, gdy istnieje rozwiązanie.
Jewgienij Afanasiew
1
Wydaje mi się, że powodem byłoby wyświetlenie informacji o postępie podczas przesyłania.
Prakhar Mishra
32

Rozwiązaniem, które znalazłem, było <form>ukrycie celu iFrame. Ramka iFrame może następnie uruchomić JS, aby wyświetlić użytkownikowi, że jest kompletny (podczas ładowania strony).

Darryl Hein
źródło
1
jestem zainteresowany tą odpowiedzią, czy masz wersję demonstracyjną, z którą możesz połączyć?
lfender6445
32

Napisałem to w środowisku Rails . To tylko około pięciu wierszy JavaScript, jeśli używasz lekkiej wtyczki jQuery.

Wyzwaniem jest uruchomienie przesyłania AJAX, ponieważ standard remote_form_fornie rozumie przesyłania formularzy wieloczęściowych. Nie będzie wysyłał danych pliku, którego Rails szuka z żądaniem AJAX.

Właśnie wtedy pojawia się wtyczka jQuery-form.

Oto kod Railsów:

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

Oto powiązany JavaScript:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

A oto akcja kontrolera Railsów, całkiem waniliowa:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

Używam tego od kilku tygodni z Bloggity i działa jak mistrz.

wbharding
źródło
31

Simple Ajax Uploader to kolejna opcja:

https://github.com/LPology/Simple-Ajax-Uploader

  • Wiele przeglądarek - działa w IE7 +, Firefox, Chrome, Safari, Opera
  • Obsługuje wielokrotne jednoczesne przesyłanie - nawet w przeglądarkach innych niż HTML5
  • Bez flashowania lub zewnętrznego CSS - tylko jeden plik Javascript 5Kb
  • Opcjonalne, wbudowane wsparcie dla pasków postępu w różnych przeglądarkach (przy użyciu rozszerzenia APC PHP)
  • Elastyczny i wysoce konfigurowalny - użyj dowolnego elementu jako przycisku przesyłania, stylizuj własne wskaźniki postępu
  • Nie wymaga formularzy, wystarczy podać element, który będzie służył jako przycisk przesyłania
  • Licencja MIT - bezpłatna do wykorzystania w projekcie komercyjnym

Przykładowe użycie:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // upload button
    url: '/uploadhandler', // URL of server-side upload handler
    name: 'userfile', // parameter name of the uploaded file
    onSubmit: function() {
        this.setProgressBar( $('#progressBar') ); // designate elem as our progress bar
    },
    onComplete: function(file, response) {
        // do whatever after upload is finished
    }
});
użytkownik1091949
źródło
2
To wydaje się być jak dotąd najbardziej obiecujące. Miałeś mnie IE7+! Wypróbuj teraz. Dzięki
Pierre
25

jQuery Uploadify to kolejna dobra wtyczka, której użyłem wcześniej do przesyłania plików. Kod JavaScript jest tak prosty, jak: kod. Jednak nowa wersja nie działa w przeglądarce Internet Explorer.

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

Przeprowadziłem wiele poszukiwań i doszedłem do innego rozwiązania do przesyłania plików bez żadnej wtyczki i tylko z ajaxem. Rozwiązanie jest następujące:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}
farnoush resa
źródło
2
Uploadify nie żyje od lat. Nie jest już obsługiwany ani utrzymywany.
Ray Nicholus,
24

Oto kolejne rozwiązanie dotyczące sposobu przesyłania pliku ( bez żadnej wtyczki )

Korzystanie z prostych skryptów JavaScript i AJAX (z paskiem postępu)

Część HTML

<form id="upload_form" enctype="multipart/form-data" method="post">
    <input type="file" name="file1" id="file1"><br>
    <input type="button" value="Upload File" onclick="uploadFile()">
    <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
    <h3 id="status"></h3>
    <p id="loaded_n_total"></p>
</form>

Część JS

function _(el){
    return document.getElementById(el);
}
function uploadFile(){
    var file = _("file1").files[0];
    // alert(file.name+" | "+file.size+" | "+file.type);
    var formdata = new FormData();
    formdata.append("file1", file);
    var ajax = new XMLHttpRequest();
    ajax.upload.addEventListener("progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);
    ajax.open("POST", "file_upload_parser.php");
    ajax.send(formdata);
}
function progressHandler(event){
    _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
    var percent = (event.loaded / event.total) * 100;
    _("progressBar").value = Math.round(percent);
    _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
    _("status").innerHTML = event.target.responseText;
    _("progressBar").value = 0;
}
function errorHandler(event){
    _("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
    _("status").innerHTML = "Upload Aborted";
}

Część PHP

<?php
$fileName = $_FILES["file1"]["name"]; // The file name
$fileTmpLoc = $_FILES["file1"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["file1"]["type"]; // The type of file it is
$fileSize = $_FILES["file1"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["file1"]["error"]; // 0 for false... and 1 for true
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
}
if(move_uploaded_file($fileTmpLoc, "test_uploads/$fileName")){ // assuming the directory name 'test_uploads'
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}
?>

Oto przykładowa aplikacja

Siddhartha Chowdhury
źródło
19
var formData=new FormData();
formData.append("fieldname","value");
formData.append("image",$('[name="filename"]')[0].files[0]);

$.ajax({
    url:"page.php",
    data:formData,
    type: 'POST',
    dataType:"JSON",
    cache: false,
    contentType: false,
    processData: false,
    success:function(data){ }
});

Możesz użyć danych formularza do opublikowania wszystkich swoich wartości, w tym obrazów.

Vivek Aasaithambi
źródło
6
Uwaga: cache: falsejest nadmiarowy na POSTżądanie, ponieważ POST nigdy nie buforuje.
Gone Coding
@Vivek Aasaithambi, dostałem ten błąd:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
candlejack,
15

Aby przesłać plik asynchronicznie za pomocą Jquery, wykonaj następujące czynności:

krok 1 W swoim projekcie otwórz menedżera Nuget i dodaj pakiet (pobierz plik jquery (wystarczy, że napiszesz go w polu wyszukiwania, pojawi się i zainstaluje.)) URL: https://github.com/blueimp/jQuery-File- Przekazać plik

krok 2 Dodaj poniższe skrypty w plikach HTML, które zostały już dodane do projektu, uruchamiając powyższy pakiet:

jquery.ui.widget.js

jquery.iframe-transport.js

jquery.fileupload.js

krok 3 Napisz kontrolę przesyłania pliku zgodnie z poniższym kodem:

<input id="upload" name="upload" type="file" />

krok 4 napisz metodę js jako uploadFile jak poniżej:

 function uploadFile(element) {

            $(element).fileupload({

                dataType: 'json',
                url: '../DocumentUpload/upload',
                autoUpload: true,
                add: function (e, data) {           
                  // write code for implementing, while selecting a file. 
                  // data represents the file data. 
                  //below code triggers the action in mvc controller
                  data.formData =
                                    {
                                     files: data.files[0]
                                    };
                  data.submit();
                },
                done: function (e, data) {          
                   // after file uploaded
                },
                progress: function (e, data) {

                   // progress
                },
                fail: function (e, data) {

                   //fail operation
                },
                stop: function () {

                  code for cancel operation
                }
            });

        };

krok 5 Po przesłaniu pliku elementu wywołania funkcji gotowej, aby zainicjować proces, jak opisano poniżej:

$(document).ready(function()
{
    uploadFile($('#upload'));

});

krok 6 Napisz kontroler MVC i akcję zgodnie z poniższym opisem:

public class DocumentUploadController : Controller
    {       

        [System.Web.Mvc.HttpPost]
        public JsonResult upload(ICollection<HttpPostedFileBase> files)
        {
            bool result = false;

            if (files != null || files.Count > 0)
            {
                try
                {
                    foreach (HttpPostedFileBase file in files)
                    {
                        if (file.ContentLength == 0)
                            throw new Exception("Zero length file!");                       
                        else 
                            //code for saving a file

                    }
                }
                catch (Exception)
                {
                    result = false;
                }
            }


            return new JsonResult()
                {
                    Data=result
                };


        }

    }
Ashish
źródło
14

Nowoczesne podejście bez Jquery jest użycie FileList obiekt wrócisz od <input type="file">kiedy wybiera użytkownika pliku (ów), a następnie użyć Fetch aby opublikować FileList owinięty wokół FormData obiekt.

// The input DOM element // <input type="file">
const inputElement = document.querySelector('input[type=file]');

// Listen for a file submit from user
inputElement.addEventListener('change', () => {
    const data = new FormData();
    data.append('file', inputElement.files[0]);
    data.append('imageName', 'flower');

    // You can then post it to your server.
    // Fetch can accept an object of type FormData on its  body
    fetch('/uploadImage', {
        method: 'POST',
        body: data
    });
});
Alister
źródło
Najwyraźniej nieobsługiwany w IE
Marco Demaio
11

Tutaj możesz zobaczyć rozwiązane rozwiązanie z działającą wersją demonstracyjną , która umożliwia podgląd i przesłanie plików formularza na serwer. W twoim przypadku musisz użyć Ajax, aby ułatwić przesyłanie pliku na serwer:

<from action="" id="formContent" method="post" enctype="multipart/form-data">
    <span>File</span>
    <input type="file" id="file" name="file" size="10"/>
    <input id="uploadbutton" type="button" value="Upload"/>
</form>

Przesyłane dane są danymi formularza. W jQuery użyj funkcji przesyłania formularza zamiast kliknięcia przycisku, aby przesłać plik formularza, jak pokazano poniżej.

$(document).ready(function () {
   $("#formContent").submit(function(e){

     e.preventDefault();
     var formdata = new FormData(this);

 $.ajax({
     url: "ajax_upload_image.php",
     type: "POST",
     data: formdata,
     mimeTypes:"multipart/form-data",
     contentType: false,
     cache: false,
     processData: false,
     success: function(){

     alert("successfully submitted");

     });
   });
});

Zobacz więcej szczegółów

Daniel Nyamasyo
źródło
11

Przykład: Jeśli używasz jQuery, możesz łatwo załadować plik. Jest to niewielka i silna wtyczka jQuery, http://jquery.malsup.com/form/ .

Przykład

var $bar   = $('.ProgressBar');
$('.Form').ajaxForm({
  dataType: 'json',

  beforeSend: function(xhr) {
    var percentVal = '0%';
    $bar.width(percentVal);
  },

  uploadProgress: function(event, position, total, percentComplete) {
    var percentVal = percentComplete + '%';
    $bar.width(percentVal)
  },

  success: function(response) {
    // Response
  }
});

Mam nadzieję, że byłoby to pomocne

MEAbid
źródło
10

Możesz użyć

$(function() {
    $("#file_upload_1").uploadify({
        height        : 30,
        swf           : '/uploadify/uploadify.swf',
        uploader      : '/uploadify/uploadify.php',
        width         : 120
    });
});

Próbny

Amit
źródło
9

Konwersja plików do base64 korzystających | HTML5 za readAsDataURL () lub niektóre base64 enkoder . Fiddle tutaj

var reader = new FileReader();

        reader.onload = function(readerEvt) {
            var binaryString = readerEvt.target.result;
            document.getElementById("base64textarea").value = btoa(binaryString);
        };

        reader.readAsBinaryString(file);

Następnie, aby pobrać:

window.open("data:application/octet-stream;base64," + base64);
tnt-rox
źródło
9

Możesz przekazać dodatkowe parametry wraz z nazwą pliku podczas wykonywania asynchronicznego przesyłania za pomocą XMLHttpRequest (bez zależności flash i iframe). Dołącz wartość dodatkowego parametru do FormData i wyślij żądanie przesłania.


var formData = new FormData();
formData.append('parameter1', 'value1');
formData.append('parameter2', 'value2'); 
formData.append('file', $('input[type=file]')[0].files[0]);

$.ajax({
    url: 'post back url',
    data: formData,
// other attributes of AJAX
});

Ponadto przesyłanie pliku interfejsu JavaScript Syncfusion zapewnia rozwiązanie dla tego scenariusza po prostu za pomocą argumentu zdarzenia. dokumentację można znaleźć tutaj, a dalsze szczegóły na temat tej kontroli tutaj wprowadź opis linku tutaj

Karthik Ravichandran
źródło
8

Poszukaj obsługi procesu przesyłania pliku, asynchronicznie tutaj: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Próbka z linku

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>
Allende
źródło
7

To jest moje rozwiązanie.

<form enctype="multipart/form-data">    

    <div class="form-group">
        <label class="control-label col-md-2" for="apta_Description">Description</label>
        <div class="col-md-10">
            <input class="form-control text-box single-line" id="apta_Description" name="apta_Description" type="text" value="">
        </div>
    </div>

    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

i js

<script>

    $(':button').click(function () {
        var formData = new FormData($('form')[0]);
        $.ajax({
            url: '@Url.Action("Save", "Home")',  
            type: 'POST',                
            success: completeHandler,
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
    });    

    function completeHandler() {
        alert(":)");
    }    
</script>

Kontroler

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    [...]
}
Erick Langford Xenes
źródło
2
Wygląda na to, że do swojej odpowiedzi wmieszałeś jakieś ramy. Powinieneś przynajmniej wymienić ramy, dla których twoja odpowiedź jest użyteczna. Jeszcze lepiej, usuń wszystkie elementy frameworka i pokaż tylko odpowiedź na postawione pytanie.
Zero3,
2
więc w rzeczywistości istnieje platforma mvc o nazwie „mvc”? i używa składni csharpish? to okrutne.
nonchip
6

Używając HTML5 i JavaScript , przesyłanie asynchroniczne jest dość łatwe, tworzę logikę przesyłania razem z twoim HTML, to nie działa w pełni, ponieważ wymaga interfejsu API, ale zademonstruj, jak to działa, jeśli masz punkt końcowy wywoływany /uploadz katalogu głównego witryny, ten kod powinien działać dla Ciebie:

const asyncFileUpload = () => {
  const fileInput = document.getElementById("file");
  const file = fileInput.files[0];
  const uri = "/upload";
  const xhr = new XMLHttpRequest();
  xhr.upload.onprogress = e => {
    const percentage = e.loaded / e.total;
    console.log(percentage);
  };
  xhr.onreadystatechange = e => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log("file uploaded");
    }
  };
  xhr.open("POST", uri, true);
  xhr.setRequestHeader("X-FileName", file.name);
  xhr.send(file);
}
<form>
  <span>File</span>
  <input type="file" id="file" name="file" size="10" />
  <input onclick="asyncFileUpload()" id="upload" type="button" value="Upload" />
</form>

Również dodatkowe informacje na temat XMLHttpReques:

Obiekt XMLHttpRequest

Wszystkie nowoczesne przeglądarki obsługują obiekt XMLHttpRequest. Obiekt XMLHttpRequest może służyć do wymiany danych z serwerem sieciowym za kulisami. Oznacza to, że można aktualizować części strony bez ponownego ładowania całej strony.


Utwórz obiekt XMLHttpRequest

Wszystkie nowoczesne przeglądarki (Chrome, Firefox, IE7 +, Edge, Safari, Opera) mają wbudowany obiekt XMLHttpRequest.

Składnia do tworzenia obiektu XMLHttpRequest:

zmienna = nowa XMLHttpRequest ();


Dostęp do różnych domen

Ze względów bezpieczeństwa nowoczesne przeglądarki nie pozwalają na dostęp do różnych domen.

Oznacza to, że zarówno strona internetowa, jak i plik XML, który próbuje załadować, muszą znajdować się na tym samym serwerze.

Przykłady W3Schools wszystkie otwarte pliki XML znajdujące się w domenie W3Schools.

Jeśli chcesz użyć powyższego przykładu na jednej ze swoich stron internetowych, ładowane pliki XML muszą znajdować się na twoim serwerze.

Aby uzyskać więcej informacji, możesz kontynuować czytanie tutaj ...

Alireza
źródło
5

Możesz użyć nowszego Fetch API przez JavaScript. Lubię to:

function uploadButtonCLicked(){
    var input = document.querySelector('input[type="file"]')

    fetch('/url', {
      method: 'POST',
      body: input.files[0]
    }).then(res => res.json())   // you can do something with response
      .catch(error => console.error('Error:', error))
      .then(response => console.log('Success:', response));
}                               

Zaleta: Fetch API jest natywnie obsługiwany przez wszystkie nowoczesne przeglądarki, więc nie musisz niczego importować. Zauważ też, że funkcja fetch () zwraca obietnicę, która jest następnie obsługiwana przy użyciu .then(..code to handle response..)asynchronicznie.

Czarnobrody
źródło
4

Możesz wykonać asynchroniczne przesyłanie wielu plików za pomocą JavaScript lub jQuery i to bez użycia żadnej wtyczki. Możesz również pokazać postęp przesyłania pliku w czasie rzeczywistym w kontrolce postępu. Znalazłem 2 fajne linki -

  1. Oparta na ASP.NET Web Forms funkcja Mulitple File Upload z paskiem postępu
  2. Wielokrotne przesyłanie plików oparte na ASP.NET MVC wykonane w jQuery

Językiem po stronie serwera jest C #, ale możesz wprowadzić pewne modyfikacje, aby działał z innym językiem, takim jak PHP.

Przesyłanie pliku ASP.NET Core MVC:

W widoku Utwórz kontrolkę przesyłania plików w HTML:

<form method="post" asp-action="Add" enctype="multipart/form-data">
    <input type="file" multiple name="mediaUpload" />
    <button type="submit">Submit</button>
</form>

Teraz utwórz metodę działania w kontrolerze:

[HttpPost]
public async Task<IActionResult> Add(IFormFile[] mediaUpload)
{
    //looping through all the files
    foreach (IFormFile file in mediaUpload)
    {
        //saving the files
        string path = Path.Combine(hostingEnvironment.WebRootPath, "some-folder-path"); 
        using (var stream = new FileStream(path, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
    }
}

Zmienna hostEnvironment jest typu IHostingEnvironment, którą można wstrzykiwać do kontrolera za pomocą wstrzykiwania zależności, np .:

private IHostingEnvironment hostingEnvironment;
public MediaController(IHostingEnvironment environment)
{
    hostingEnvironment = environment;
}
Joe Clinton
źródło
Czy możesz podać istotę rozwiązania w swojej odpowiedzi, ponieważ w przeciwnym razie może stać się bezużyteczne, jeśli połączona witryna zmieni się lub przejdzie w tryb offline.
Dima Kozhevin,
4

W przypadku PHP poszukaj https://developer.hyvor.com/php/image-upload-ajax-php-mysql

HTML

<html>
<head>
    <title>Image Upload with AJAX, PHP and MYSQL</title>
</head>
<body>
<form onsubmit="submitForm(event);">
    <input type="file" name="image" id="image-selecter" accept="image/*">
    <input type="submit" name="submit" value="Upload Image">
</form>
<div id="uploading-text" style="display:none;">Uploading...</div>
<img id="preview">
</body>
</html>

JAVASCRIPT

var previewImage = document.getElementById("preview"),  
    uploadingText = document.getElementById("uploading-text");

function submitForm(event) {
    // prevent default form submission
    event.preventDefault();
    uploadImage();
}

function uploadImage() {
    var imageSelecter = document.getElementById("image-selecter"),
        file = imageSelecter.files[0];
    if (!file) 
        return alert("Please select a file");
    // clear the previous image
    previewImage.removeAttribute("src");
    // show uploading text
    uploadingText.style.display = "block";
    // create form data and append the file
    var formData = new FormData();
    formData.append("image", file);
    // do the ajax part
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function() {
        if (this.readyState === 4 && this.status === 200) {
            var json = JSON.parse(this.responseText);
            if (!json || json.status !== true) 
                return uploadError(json.error);

            showImage(json.url);
        }
    }
    ajax.open("POST", "upload.php", true);
    ajax.send(formData); // send the form data
}

PHP

<?php
$host = 'localhost';
$user = 'user';
$password = 'password';
$database = 'database';
$mysqli = new mysqli($host, $user, $password, $database);


 try {
    if (empty($_FILES['image'])) {
        throw new Exception('Image file is missing');
    }
    $image = $_FILES['image'];
    // check INI error
    if ($image['error'] !== 0) {
        if ($image['error'] === 1) 
            throw new Exception('Max upload size exceeded');

        throw new Exception('Image uploading error: INI Error');
    }
    // check if the file exists
    if (!file_exists($image['tmp_name']))
        throw new Exception('Image file is missing in the server');
    $maxFileSize = 2 * 10e6; // in bytes
    if ($image['size'] > $maxFileSize)
        throw new Exception('Max size limit exceeded'); 
    // check if uploaded file is an image
    $imageData = getimagesize($image['tmp_name']);
    if (!$imageData) 
        throw new Exception('Invalid image');
    $mimeType = $imageData['mime'];
    // validate mime type
    $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($mimeType, $allowedMimeTypes)) 
        throw new Exception('Only JPEG, PNG and GIFs are allowed');

    // nice! it's a valid image
    // get file extension (ex: jpg, png) not (.jpg)
    $fileExtention = strtolower(pathinfo($image['name'] ,PATHINFO_EXTENSION));
    // create random name for your image
    $fileName = round(microtime(true)) . mt_rand() . '.' . $fileExtention; // anyfilename.jpg
    // Create the path starting from DOCUMENT ROOT of your website
    $path = '/examples/image-upload/images/' . $fileName;
    // file path in the computer - where to save it 
    $destination = $_SERVER['DOCUMENT_ROOT'] . $path;

    if (!move_uploaded_file($image['tmp_name'], $destination))
        throw new Exception('Error in moving the uploaded file');

    // create the url
    $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
    $domain = $protocol . $_SERVER['SERVER_NAME'];
    $url = $domain . $path;
    $stmt = $mysqli -> prepare('INSERT INTO image_uploads (url) VALUES (?)');
    if (
        $stmt &&
        $stmt -> bind_param('s', $url) &&
        $stmt -> execute()
    ) {
        exit(
            json_encode(
                array(
                    'status' => true,
                    'url' => $url
                )
            )
        );
    } else 
        throw new Exception('Error in saving into the database');

} catch (Exception $e) {
    exit(json_encode(
        array (
            'status' => false,
            'error' => $e -> getMessage()
        )
    ));
}
Supun Kavinda
źródło
4

Możesz również rozważyć użycie czegoś takiego jak https://uppy.io .

Wykonuje przesyłanie plików bez opuszczania strony i oferuje kilka bonusów, takich jak przeciąganie i upuszczanie, wznawianie przesyłania w przypadku awarii przeglądarki / niestabilnych sieci oraz importowanie np. Z Instagrama. Jest to oprogramowanie typu open source i nie opiera się na jQuery / React / Angular / Vue, ale można z nim korzystać. Oświadczenie: jako twórca jestem stronniczy;)

kvz
źródło
Powyższy link nie działa. Oto github: github.com/transloadit/uppy
Chris Charles
uppy.io ma kopię zapasową stron CloudFlare + GitHub? Nadal przydatne jest jednak posiadanie bezpośredniego linku do repozytorium :)
kvz