Come posso caricare i file in modo asincrono?


2914

Vorrei caricare un file in modo asincrono con 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"/>

Invece di caricare il file, sto solo ottenendo il nome del file. Cosa posso fare per risolvere questo problema?


Esistono vari plug-in pronti per il caricamento di file per jQuery. Fare questo tipo di upload di hack non è un'esperienza piacevole, quindi alla gente piace usare soluzioni già pronte. Ecco alcuni: - File Uploader JQuery - multipla Upload di file Plugin - Mini File Upload multiplo - File Upload jQuery È possibile cercare più progetti sul NPM (usando "jquery-plugin", come la parola) o su Github.
Allegro

72
stai solo ottenendo il nome del file perché il tuo nome file var sta ottenendo il valore di $ ('# file'), non il file che si trova nell'input
Jimmy

21
Eccone una buona: http://blueimp.github.io/jQuery-File-Upload/ - Caricamento HTML5 ajax - Graceback fallace agli iframe per browser non supportati - Caricamento asincrono multi-file L'abbiamo usato e funziona benissimo. ( Documentazione qui )
Ashish Panery,

3
Controlla anche questo: stackoverflow.com/questions/6974684/… , qui spiega come raggiungerlo tramite jQuery
Chococroc,

2
@Jimmy Come otterrebbe invece il file che si trova nell'input?
alex,

Risposte:


2519

Con HTML5 è possibile effettuare caricamenti di file con Ajax e jQuery. Non solo, puoi eseguire convalide dei file (nome, dimensione e tipo MIME) o gestire l'evento progress con il tag progress HTML5 (o un div). Di recente ho dovuto creare un file uploader, ma non volevo usare Flash né Iframe o plugin e dopo alcune ricerche ho trovato la soluzione.

HTML:

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

Per prima cosa, puoi fare un po 'di validazione se vuoi. Ad esempio, nel .on('change')caso del file:

$(':file').on('change', function () {
  var file = this.files[0];

  if (file.size > 1024) {
    alert('max upload size is 1k');
  }

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

Ora $.ajax()invia con il clic del pulsante:

$(':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;
    }
  });
});

Come puoi vedere, con HTML5 (e alcune ricerche) il caricamento di file non solo diventa possibile ma super facile. Provalo con Google Chrome poiché alcuni dei componenti HTML5 degli esempi non sono disponibili in tutti i browser.


14
Posso quindi usare $ _FILES in upload.php?
Alessandro Cosentino,

71
Questo dovrebbe funzionare in Internet Explorer ma solo nella versione 10. ( caniuse.com/xhr2 )
Tyler

18
Ciao, apprezzo che PHP sia la tua lingua preferita ... ma mi chiedo se sai se funziona anche in ASP.NET MVC? Sono uno sviluppatore .NET e ho cercato di utilizzare il tuo semplice esempio per eseguire il caricamento di file AJAX ma sul lato server non riesco a ottenere il file che ho pubblicato tramite AJAX. Sto usando l'ultimo Chrome.
Shumii,

25
È FormData che fa tutta la magia qui. Assicurati di controllare questi documenti: copre tutte le tue domande su più file e campi.
incarnato il

4
Solo così qualcun altro non passa ore ... name="file"è molto importante sul <input>tag file se intendi utilizzare i dati in PHP (e probabilmente in altri luoghi). Ho creato un modulo in modo dinamico utilizzando JavaScript, quindi non avevo bisogno dell'attributo name ma ho scoperto nel modo più assoluto che è necessario per recuperare il lato server dei dati.
Kivak Wolf,

273

Aggiornamento 2019: dipende ancora dai browser utilizzati dal tuo gruppo demografico.

Una cosa importante da capire con la "nuova" fileAPI HTML5 è che non era supportato fino a IE 10 . Se il mercato specifico a cui stai mirando ha una propensione superiore alla media verso le versioni precedenti di Windows, potresti non avere accesso ad esso.

A partire dal 2017, circa il 5% dei browser è uno di IE 6, 7, 8 o 9. Se ti dirigi in una grande azienda (ad esempio, questo è uno strumento B2B o qualcosa che stai offrendo per la formazione) quel numero può salire alle stelle . Nel 2016 ho avuto a che fare con un'azienda che utilizza IE8 su oltre il 60% delle loro macchine.

È il 2019 a partire da questa modifica, quasi 11 anni dopo la mia risposta iniziale. IE9 e inferiori sono globalmente intorno al segno dell'1% ma ci sono ancora cluster di maggiore utilizzo.

L'importante asporto da ciò, qualunque sia la funzione, è controllare quale browser utilizzano i tuoi utenti . In caso contrario, imparerai una lezione rapida e dolorosa sul perché "funziona per me" non è abbastanza buono in un prodotto da consegnare a un cliente. caniuse è uno strumento utile ma nota da dove ottengono i loro dati demografici. Potrebbero non allinearsi con i tuoi. Questo non è mai più vero degli ambienti aziendali.

Segue la mia risposta del 2008.


Tuttavia, ci sono metodi non JS praticabili per il caricamento di file. Puoi creare un iframe sulla pagina (che nascondi con CSS) e quindi scegliere come target il tuo modulo per pubblicare su quell'iframe. Non è necessario spostare la pagina principale.

È un post "reale", quindi non è completamente interattivo. Se è necessario lo stato, è necessario qualcosa sul lato server per elaborarlo. Questo varia notevolmente a seconda del server. ASP.NET ha meccanismi più belli. PHP fallisce, ma puoi usare le modifiche Perl o Apache per aggirare il problema.

Se hai bisogno di più caricamenti di file, è meglio eseguire ogni file uno alla volta (per superare i limiti massimi di caricamento dei file). Pubblica il primo modulo nell'iframe, monitora i suoi progressi usando quanto sopra e quando ha finito, pubblica il secondo modulo nell'iframe e così via.

Oppure usa una soluzione Java / Flash. Sono molto più flessibili in ciò che possono fare con i loro post ...


142
Per la cronaca è ora possibile eseguire upload di file AJAX puri se il browser supporta l'API File - developer.mozilla.org/en/using_files_from_web_applications
meleyal

La soluzione iframe è piuttosto semplice e facile da far funzionare
Matthew Lock,

questa è una risposta piuttosto vecchia, ma è stata un po 'fuorviante .. IE ha supportato XHR in modo nativo fino a IE7 e lo ha supportato tramite ActiveX fino a IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp . Il modo pratico per farlo era sicuramente quello di prendere di mira i componenti flash (onde d'urto) o di implementare un controllo Flash / ActiveX (Silverlight). Se è possibile originare una richiesta e gestire la risposta tramite javascript, è ajax .. tuttavia, detto questo, ajax è sinonimo di xhr, ma non descrive da sé il meccanismo / i componenti di sottolineatura che consegna / scambia il payload.
Brett Caswell,

4
@BrettCaswell Non stavo dicendo che AJAX / XHR non fosse possibile, solo che non era possibile pubblicare un file con loro su vecchie versioni - ma eterne - di IE. Questo era e rimane completamente vero.
Oli,

Non è così, questa è un'opinione UX - forse è valida.
Nimjox,

112

A questo scopo, consiglio di utilizzare il plugin Fine Uploader . Il tuo JavaScriptcodice sarebbe:

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

Usa JSON - quindi per la vecchia versione di PHP non sarà possibile utilizzarlo.
Lorenzo Manucci,

Sembra molto più pulito di Ajax File Upload, dove ho bisogno di includere un enorme pezzo di codice solo per usare quella dannata cosa.
ripper234,

L'URL più recente per la versione 2 è ora valums-file-uploader.github.com/file-uploader
Simon East

35
"Questo plugin è open source in GNU GPL 2 o successivo e GNU LGPL 2 o successivo." Quindi finché non distribuisci la copia o una versione modificata, non devi aprire il tuo progetto.
Trantor Liu,

Mi sto perdendo qualcosa? Questa libreria non sembra più usare jquery, quindi non supporta la sintassi dalla risposta?
James McCormack,

102

Nota: questa risposta è obsoleta, ora è possibile caricare file usando XHR.


Non è possibile caricare file utilizzando XMLHttpRequest (Ajax). Puoi simulare l'effetto usando un iframe o Flash. L'ottimo plug-in jQuery Form che pubblica i tuoi file attraverso un iframe per ottenere l'effetto.


1
Sì, puoi inviare a un iframe e acquisire il file lì. Ho un'esperienza molto limitata con questo, quindi non posso davvero commentarlo.
Mattias,

15
Piccola osservazione: nelle ultime versioni di Chrome e Firefox è possibile, stackoverflow.com/questions/4856917/…
Alleo,

Non supportato in IE9 e meno
Radmation

96

In conclusione per i futuri lettori.

Caricamento file asincrono

Con HTML5

Puoi caricare file con jQuery usando il $.ajax()metodo se FormData e l' API File sono supportati (entrambe le funzionalità HTML5).

Puoi anche inviare file senza FormData ma in entrambi i casi l'API File deve essere presente per elaborare i file in modo tale che possano essere inviati con 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!");
});

Per un rapido, puro esempio JavaScript ( no jQuery ) vedere " Invio di file mediante un oggetto FormData ".

Ricaderci

Quando HTML5 non è supportato (nessuna API File ) l'unica altra soluzione JavaScript pura (senza Flash o qualsiasi altro plug-in del browser) è la tecnica iframe nascosta , che consente di emulare una richiesta asincrona senza utilizzare l' oggetto XMLHttpRequest .

Consiste nell'impostare un iframe come destinazione del modulo con gli input del file. Quando l'utente invia una richiesta, i file vengono caricati ma la risposta viene visualizzata all'interno dell'iframe invece di eseguire nuovamente il rendering della pagina principale. Nascondere l'iframe rende l'intero processo trasparente per l'utente ed emula una richiesta asincrona.

Se fatto correttamente, dovrebbe funzionare virtualmente su qualsiasi browser, ma presenta alcune avvertenze su come ottenere la risposta dall'iframe.

In questo caso potresti preferire l'uso di un plugin wrapper come Bifröst che utilizza la tecnica iframe ma fornisce anche un trasporto jQuery Ajax che consente di inviare file con solo il $.ajax()metodo come questo:

$.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!");
});

plugin

Bifröst è solo un piccolo wrapper che aggiunge il supporto di fallback al metodo ajax di jQuery, ma molti dei plug-in summenzionati come jQuery Form Plugin o jQuery File Upload includono l'intero stack da HTML5 a fallback diversi e alcune utili funzionalità per facilitare il processo. A seconda delle tue esigenze e requisiti, potresti voler prendere in considerazione un'implementazione semplice o uno di questi plugin.


3
Una cosa da notare, in base alla documentazione: è necessario inviare anche contentType: false. Quando non l'ho inviato con Chrome, il tipo di contenuto del modulo è stato invalidato da jQuery.
ash

Bella risposta. Alcuni suggerimenti di miglioramento: Rimuovere le parti del codice non collegati alla risposta, ad esempio, la .done()e .fail()callback. Inoltre, un esempio senza l'uso di FormDatae un elenco di vantaggi / svantaggi sarebbe fantastico.
Zero3

Ho ricevuto questo errore:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
Candlejack il

85

Questo plugin jQuery per il caricamento di file AJAX carica il file da qualche parte e trasmette la risposta a una richiamata, nient'altro.

  • Non dipende da HTML specifico, basta dargli un <input type="file">
  • Non richiede che il tuo server risponda in alcun modo particolare
  • Non importa quanti file usi o dove si trovano nella pagina

- Usa solo -

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

- o quanto -

$('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');
  }
});

1
@ user840250 jQuery 1.9.1?
Jordan Feldstein,

62

Ho usato lo script seguente per caricare immagini che sembrano funzionare bene.

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

Spiegazione

Uso la risposta divper mostrare l'animazione del caricamento e la risposta al termine del caricamento.

La parte migliore è che puoi inviare dati extra come ids ecc. Con il file quando usi questo script. L'ho menzionato extra-datacome nella sceneggiatura.

A livello di PHP funzionerà come un normale caricamento di file. i dati extra possono essere recuperati come $_POSTdati.

Qui non stai usando un plugin e roba del genere. Puoi modificare il codice come desideri. Non stai codificando ciecamente qui. Questa è la funzionalità principale di qualsiasi caricamento di file jQuery. In realtà Javascript.


5
-1 per l'utilizzo di jQuery e non per l'utilizzo del motore di selezione e dei gestori di eventi. addEventListenernon è cross-browser.
Segna il

3
Perché sarebbe inutile aggiungere una risposta separata che si baserebbe principalmente su questa, con solo alcune modifiche. Invece, questa risposta dovrebbe essere corretta.
Segna il

2
@RainFromHeaven, per favore, puoi modificare la risposta? Non so come farlo nel modo cross-browser.
Thiago Negri,

2
Non funziona ancora in IE 9 e versioni precedenti. Gli utenti utilizzano ancora quelle versioni di IE.
Pierre,

1
Qualcuno può spiegare come può essere fatto funzionare in asp.net? Uso il webmethod? Se sì, come sarebbe?
Samurai Jack,

49

Puoi farlo in JavaScript vaniglia abbastanza facilmente. Ecco uno snippet del mio progetto attuale:

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

3
@Gary: mi dispiace, avrei dovuto postare anche quel bit. Stavo solo usando la nuova funzionalità di trascinamento della selezione in HTML5; puoi trovare un esempio qui: html5demos.com/file-api#view-source - fai semplicemente clic su "visualizza sorgente". In sostanza, all'interno ondropdell'evento puoi farevar file = e.dataTransfer.files[0]
aprire il

Forse la domanda è stata modificata da allora, ma alcune persone in una discussione aperta che ho aperto pensano che una risposta JS alla vaniglia sia fuori tema se OP richiede una soluzione jQuery (a condizione che ne esista una) e tali risposte appartengano a una domanda separata.
Andy,

4
@Andy Beh, non sono d'accordo, e sembra che anche altri 34 lo facciano. Se puoi usare jQuery, puoi sicuramente usare JavaScript. In ogni caso, questo è un sito della comunità - non è solo OP che sto cercando di aiutare qui. Tutti sono liberi di scegliere / utilizzare la risposta che preferiscono. Alcune persone gravitano solo verso jQuery perché pensano che sarà molto più facile / meno righe di codice, quando in realtà non hanno bisogno del sovraccarico di una libreria aggiuntiva.
Aprire il

47

Puoi caricare semplicemente con 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) {
                // ...
            }
       });
    }));
});

1
@RaydenBlack only jQuery.
Zayn Ali,

come ottenere l'avanzamento del caricamento?
Ali Sherafat,

44

Il modo più semplice e robusto che ho fatto in passato è semplicemente quello di scegliere come target un tag iFrame nascosto con il tuo modulo, quindi verrà inviato all'interno dell'iframe senza ricaricare la pagina.

Cioè se non si desidera utilizzare un plug-in, JavaScript o qualsiasi altra forma di "magia" diversa dall'HTML. Ovviamente puoi combinarlo con JavaScript o cosa hai ...

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

Puoi anche leggere il contenuto dell'iframe onLoadper errori del server o risposte di successo e poi inviarlo all'utente.

Chrome, iFrames e onLoad

-nota- devi solo continuare a leggere se sei interessato a come impostare un blocco dell'interfaccia utente durante il caricamento / download

Attualmente Chrome non attiva l'evento onLoad per l'iframe quando viene utilizzato per trasferire file. Firefox, IE e Edge generano tutti l'evento onload per i trasferimenti di file.

L'unica soluzione che ho trovato funziona per Chrome era usare un cookie.

Per farlo fondamentalmente all'avvio del caricamento / download:

  • [Lato client] Inizia un intervallo per cercare l'esistenza di un cookie
  • [Lato server] Fai tutto il necessario con i dati del file
  • [Lato server] Imposta cookie per intervallo lato client
  • [Lato client] L'intervallo vede il cookie e lo utilizza come l'evento onLoad. Ad esempio, puoi avviare un blocco dell'interfaccia utente e quindi onLoad (o quando viene creato un cookie) rimuovi il blocco dell'interfaccia utente.

L'uso di un cookie per questo è brutto ma funziona.

Ho creato un plug-in jQuery per gestire questo problema per Chrome durante il download, che puoi trovare qui

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

Lo stesso principio base si applica anche al caricamento.

Per utilizzare il downloader (includi JS, ovviamente)

 $('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');
 });

E sul lato server, appena prima di trasferire i dati del file, creare il cookie

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

Il plug-in vedrà il cookie e quindi attiverà la onCompleterichiamata.


3
Lo adoro. Se solo qualcuno potesse menzionare i potenziali problemi con questa brillante soluzione. Davvero non capisco perché le persone lottano e usano queste ingombranti librerie e plugin quando c'è la soluzione.
Yevgeniy Afanasyev il

1
Bene, immagino che il motivo sarebbe quello di mostrare alcune informazioni sui progressi durante il caricamento.
Prakhar Mishra,

32

Una soluzione che ho trovato è stata quella di avere l' <form>obiettivo iFrame nascosto. L'iFrame può quindi eseguire JS per mostrare all'utente che è completo (al caricamento della pagina).


1
sono interessato a questa risposta, hai una demo a cui puoi collegarti?
lfender6445,

32

L'ho scritto in un ambiente Rails . Si tratta solo di cinque righe di JavaScript, se si utilizza il plug-in jQuery-form leggero.

La sfida consiste nel far funzionare il caricamento AJAX poiché lo standard remote_form_fornon comprende l'invio di moduli in più parti. Non invierà i dati del file che Rails cerca con la richiesta AJAX.

È qui che entra in gioco il plugin jQuery-form.

Ecco il codice Rails per questo:

<% 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 %>

Ecco il JavaScript associato:

$('#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.
  },
 });
});

Ed ecco l'azione del controller Rails, piuttosto vaniglia:

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

Ho usato questo nelle ultime settimane con Bloggity, e ha funzionato come un campione.


31

Simple Ajax Uploader è un'altra opzione:

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

  • Cross-browser: funziona con IE7 +, Firefox, Chrome, Safari, Opera
  • Supporta caricamenti multipli e simultanei, anche nei browser non HTML5
  • Nessun flash o CSS esterno: solo un file Javascript da 5 KB
  • Supporto opzionale opzionale per barre di avanzamento completamente cross-browser (utilizzando l'estensione APC di PHP)
  • Flessibile e altamente personalizzabile: utilizza qualsiasi elemento come pulsante di caricamento, personalizza i tuoi indicatori di progresso
  • Nessun modulo richiesto, basta fornire un elemento che fungerà da pulsante di caricamento
  • Licenza MIT - gratis da usare nel progetto commerciale

Esempio di utilizzo:

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

2
Questo sembra essere il più promettente finora, mi hai fatto IE7+! Provandolo ora. Grazie
Pierre,

25

jQuery Uploadify è un altro buon plugin che ho usato prima per caricare file. Il codice JavaScript è semplice come il seguente: codice. Tuttavia, la nuova versione non funziona in 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) {
        // ...
    }
});

Ho fatto molte ricerche e sono arrivato a un'altra soluzione per caricare file senza alcun plugin e solo con ajax. La soluzione è la seguente:

$(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);
}

2
Uploadify è morto da anni. Non più supportato o gestito.
Ray Nicholus,

24

Ecco solo un'altra soluzione su come caricare il file ( senza alcun plug-in )

Utilizzo di Javascripts semplici e AJAX (con barra di avanzamento)

Parte 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>

Parte 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";
}

Parte 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";
}
?>

Ecco l'applicazione ESEMPIO


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){ }
});

Puoi utilizzare i dati del modulo per pubblicare tutti i tuoi valori, comprese le immagini.


6
Nota: cache: falseè ridondante su una POSTrichiesta come POST mai cache.
Codice finito

@Vivek Aasaithambi, ho riscontrato questo errore:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
Candlack

15

Per caricare il file in modo asincrono con Jquery usare i passaggi seguenti:

passo 1 Nel tuo progetto apri Nuget manager e aggiungi il pacchetto (jquery fileupload (solo tu devi scriverlo nella casella di ricerca, verrà visualizzato e installato.)) URL: https://github.com/blueimp/jQuery-File- Caricare

passaggio 2 Aggiungere gli script di seguito nei file HTML, che sono già stati aggiunti al progetto eseguendo il pacchetto sopra:

jquery.ui.widget.js

jquery.iframe-transport.js

jquery.fileupload.js

passaggio 3 Scrivere il controllo di caricamento dei file secondo il codice seguente:

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

passaggio 4 scrivere un metodo js come uploadFile come di seguito:

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

        };

passaggio 5 Nella funzione ready carica il caricamento del file dell'elemento per avviare il processo come indicato di seguito:

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

});

passaggio 6 Scrivere il controller MVC e l'azione come indicato di seguito:

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
                };


        }

    }

14

Un approccio moderno senza Jquery consiste nell'utilizzare l' oggetto FileList da <input type="file">cui si ottiene quando l'utente seleziona un file (s) e quindi utilizzare Fetch per pubblicare il FileList racchiuso in un oggetto FormData .

// 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
    });
});

Apparentemente non supportato su IE
Marco Demaio il

11

Si può vedere una soluzione risolto con un lavoro demo qui che permette di visualizzare in anteprima e inviare i file del modulo al server. Nel tuo caso, devi utilizzare Ajax per facilitare il caricamento del file sul server:

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

I dati inviati sono formdata. Sul tuo jQuery, usa una funzione di invio del modulo invece di fare clic su un pulsante per inviare il file del modulo come mostrato di seguito.

$(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");

     });
   });
});

Visualizza maggiori dettagli


11

Esempio: se si utilizza jQuery, è possibile eseguire facilmente il caricamento di un file. Questo è un plug-in jQuery piccolo e potente, http://jquery.malsup.com/form/ .

Esempio

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

Spero possa essere utile


10

Puoi usare

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

dimostrazione


9

Converti il ​​file in base64 usando readAsDataURL () di HTML5 o un codificatore base64 . Violino qui

var reader = new FileReader();

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

        reader.readAsBinaryString(file);

Quindi per recuperare:

window.open("data:application/octet-stream;base64," + base64);

9

È possibile passare parametri aggiuntivi insieme al nome del file quando si effettua un caricamento asincrono utilizzando XMLHttpRequest (senza flash e dipendenza iframe). Aggiungi il valore del parametro aggiuntivo con FormData e invia la richiesta di caricamento.


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

Inoltre, il caricamento del file dell'interfaccia utente JavaScript di Syncfusion fornisce una soluzione per questo scenario usando semplicemente l'argomento dell'evento. puoi trovare la documentazione qui e ulteriori dettagli su questo controllo qui inserisci la descrizione del link qui


8

Cerca Gestione del processo di caricamento di un file, in modo asincrono qui: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Esempio dal collegamento

<?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>

7

Questa è la mia soluzione

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

e il 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>

controllore

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    [...]
}

2
Sembra che tu abbia mescolato una sorta di quadro nella tua risposta. Dovresti almeno menzionare per quale framework è utilizzabile la tua risposta. Meglio ancora, rimuovere tutti gli elementi del framework e presentare solo una risposta alla domanda posta.
Zero3

2
quindi esiste effettivamente un framework mvc chiamato "mvc"? e usa la sintassi csharpish? è crudele.
nonchip

6

Usando HTML5 e JavaScript , caricare asincrono è abbastanza semplice, creo la logica di caricamento insieme al tuo html, questo non funziona completamente in quanto ha bisogno dell'api, ma dimostra come funziona, se hai l'endpoint chiamato /uploaddalla radice del tuo sito web, questo codice dovrebbe funzionare per te:

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>

Anche alcune ulteriori informazioni su XMLHttpReques:

L'oggetto XMLHttpRequest

Tutti i browser moderni supportano l'oggetto XMLHttpRequest. L'oggetto XMLHttpRequest può essere utilizzato per scambiare dati con un server Web dietro le quinte. Ciò significa che è possibile aggiornare parti di una pagina Web, senza ricaricare l'intera pagina.


Creare un oggetto XMLHttpRequest

Tutti i browser moderni (Chrome, Firefox, IE7 +, Edge, Safari, Opera) hanno un oggetto XMLHttpRequest incorporato.

Sintassi per la creazione di un oggetto XMLHttpRequest:

variabile = nuovo XMLHttpRequest ();


Accedi a tutti i domini

Per motivi di sicurezza, i browser moderni non consentono l'accesso tra domini.

Ciò significa che sia la pagina Web che il file XML che tenta di caricare devono trovarsi sullo stesso server.

Gli esempi su W3Schools sono tutti file XML aperti situati nel dominio W3Schools.

Se si desidera utilizzare l'esempio sopra riportato su una delle proprie pagine Web, i file XML caricati devono trovarsi sul proprio server.

Per maggiori dettagli, puoi continuare a leggere qui ...


5

Puoi utilizzare l' API Fetch più recente tramite JavaScript. Come questo:

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

Vantaggio: l' API Fetch è supportata in modo nativo da tutti i browser moderni, quindi non è necessario importare nulla. Inoltre, nota che fetch () restituisce una Promessa che viene quindi gestita in .then(..code to handle response..)modo asincrono.


4

È possibile eseguire i caricamenti di file multipli asincroni utilizzando JavaScript o jQuery e quello senza utilizzare alcun plug-in. Puoi anche mostrare l'avanzamento in tempo reale del caricamento del file nel controllo dell'avanzamento. Mi sono imbattuto in 2 simpatici link:

  1. Funzione di caricamento di file mulitple basata su moduli Web ASP.NET con barra di avanzamento
  2. Upload di più file basato su ASP.NET MVC realizzato in jQuery

La lingua lato server è C # ma puoi apportare alcune modifiche per farlo funzionare con altre lingue come PHP.

Caricamento file ASP.NET Core MVC:

In Visualizza creare controllo caricamento file in html:

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

Ora crea il metodo di azione nel tuo controller:

[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);
        }
    }
}

La variabile hostingEnvironment è di tipo IHostingEnvironment che può essere iniettata nel controller usando l'iniezione di dipendenza, come:

private IHostingEnvironment hostingEnvironment;
public MediaController(IHostingEnvironment environment)
{
    hostingEnvironment = environment;
}

Potresti includere l'essenza della soluzione nella tua risposta, altrimenti potrebbe diventare inutile se il sito web collegato cambia o passa offline.
Dima Kozhevin,

4

Per PHP, cerca 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()
        )
    ));
}

4

Puoi anche prendere in considerazione l'utilizzo di qualcosa come https://uppy.io .

Effettua il caricamento di file senza allontanarsi dalla pagina e offre alcuni bonus come il trascinamento della selezione, il ripristino dei caricamenti in caso di arresti anomali del browser / reti instabili e l'importazione da ad esempio Instagram. È open source e non si basa su jQuery / React / Angular / Vue, ma può essere utilizzato con esso. Disclaimer: come suo creatore sono di parte;)


Il link sopra è morto. Ecco il github: github.com/transloadit/uppy
Chris Charles

uppy.io è supportato dalle pagine CloudFlare + GitHub e per me? Comunque è utile avere anche il collegamento diretto al repository :)
kvz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.