Як я можу завантажувати файли асинхронно?


2914

Я хотів би завантажити файл асинхронно з 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"/>

Замість завантажуваного файлу я отримую лише ім'я файлу. Що я можу зробити, щоб виправити цю проблему?


Існують різні готові плагіни для завантаження файлів для jQuery. Робити такий вид завантаження хаків - це не приємне враження, тому людям подобається використовувати готові рішення. Ось декілька: - Завантажувач файлів JQuery - Плагін для завантаження декількох файлів - Міні-завантаження декількох файлів - Завантаження файлу jQuery Ви можете шукати інші проекти в NPM (використовуючи "jquery-плагін" як ключове слово) або на Github.
Веселий

72
ви отримуєте лише ім’я файлу, оскільки ваше ім'я файлу var отримує значення $ ('# файл'), а не файл, який лежить у вході
Jimmy

21
Ось хороший варіант: http://blueimp.github.io/jQuery-File-Upload/ - завантаження ajax HTML5 - витончена резервна копія до iframes для непідтримуваних браузерів - завантаження багатофайлової асинхрології Ми використовували це, і він чудово працює. ( Документація тут )
Ashish Panery

3
Перевірте також це: stackoverflow.com/questions/6974684/… , тут пояснюється, як цього досягти за допомогою jQuery
Chococroc

2
@Jimmy Як би він отримав файл, який лежить на вході?
alex

Відповіді:


2519

За допомогою HTML5 ви можете робити завантаження файлів за допомогою Ajax та jQuery. Мало того, ви можете виконати перевірку файлів (ім’я, розмір та тип MIME) або обробити подію прогресу за допомогою тегу прогресу HTML5 (або діва). Нещодавно мені довелося зробити завантажувач файлів, але я не хотів використовувати Flash Iframes або плагіни, і після деяких досліджень я придумав рішення.

HTML:

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

По-перше, ви можете зробити певну перевірку, якщо хочете. Наприклад, у .on('change')випадку файлу:

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

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

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

Тепер $.ajax()відправте натисканням кнопки:

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

Як бачите, завантаження файлів HTML5 (і деяких досліджень) стає не тільки можливим, але і дуже простим. Спробуйте це з Google Chrome, оскільки деякі компоненти HTML5 прикладів доступні не в кожному браузері.


14
Чи можу я потім використовувати $ _FILES у upload.php?
Алессандро Косентіно

71
Це має працювати в Internet Explorer, але лише у версії 10. ( caniuse.com/xhr2 )
Тайлер

18
Привіт, я ціную PHP - це обрана вами мова ... але мені цікаво, чи знаєте ви, чи працює це також у ASP.NET MVC? Я розробник .NET, і я спробував використати ваш простий приклад, щоб зробити кілька файлів AJAX для завантаження файлів, але на стороні сервера. Я використовую найновіший Chrome.
Шумій

25
Це FormData, хто робить всю магію тут. Не забудьте перевірити ці документи - він охоплює всі ваші запитання щодо кількох файлів і полів.
втілився

4
Просто так, щоб хтось не витрачав годин ... name="file"це дуже важливо для <input>тегу файлів, якщо ви збираєтесь використовувати дані в PHP (і, мабуть, в інших місцях). Я створив форму динамічно за допомогою javascript, тому мені не потрібен атрибут імені, але я з’ясував важкий спосіб, який вам абсолютно потрібен для пошуку на сервері даних.
Ківак Вовк

273

Оновлення 2019 року: Це все ще залежить від вашого веб-переглядача демографічних використань.

Важлива річ, яку потрібно зрозуміти з «новим» fileAPI HTML5, це те, що він не підтримувався до IE 10 . Якщо конкретний ринок, на який ви прагнете, має схильність до старших версій Windows, що перевищує середню, ви можете не мати до нього доступу.

Станом на 2017 рік, близько 5% браузерів є одним із IE 6, 7, 8 або 9. Якщо ви переходите до великої корпорації (наприклад, це інструмент B2B або щось, що ви постачаєте для навчання), це число може злетіти . У 2016 році я мав справу з компанією, яка використовувала IE8 на понад 60% їх машин.

Це редакція 2019 року, майже через 11 років після моєї первинної відповіді. IE9 і нижче знаходяться в усьому світі біля позначки 1%, але все ж є скупчення з більшим рівнем використання.

Важливий Винос від цього -whatever feature- є, перевірити , який браузер ваших використовувати користувач . Якщо ви цього не зробите, ви дізнаєтесь швидкий і болісний урок, чому "працює для мене" недостатньо добре, щоб доставити клієнту. канюза - корисний інструмент, але врахуйте, звідки вони беруть демографічні показники. Вони можуть не узгоджуватися з вашими. Це ніколи не є правдивішим, ніж середовище підприємства.

Моя відповідь з 2008 року випливає.


Однак існують життєздатні не-JS методи завантаження файлів. Ви можете створити iframe на сторінці (яку ви ховаєте за допомогою CSS), а потім націлити свою форму, щоб розмістити її на цьому iframe. Не потрібно переміщувати головну сторінку.

Це "справжня" публікація, тому вона не є повністю інтерактивною. Якщо вам потрібен статус, вам потрібно щось зі сторони сервера, щоб це обробити. Це значно варіюється в залежності від вашого сервера. ASP.NET має приємніші механізми. Простий PHP не вдається, але ви можете використовувати модифікації Perl або Apache, щоб обійти його.

Якщо вам потрібно кілька завантажень файлів, найкраще робити кожен файл по одному (щоб подолати максимальний ліміт завантаження файлів). Опублікуйте першу форму в iframe, стежте за її ходом, використовуючи вищезазначені, і коли вона закінчена, опублікуйте другу форму в iframe тощо.

Або скористайтеся рішенням Java / Flash. Вони набагато гнучкіші в тому, що можуть робити зі своїми посадами ...


142
Для запису тепер можна робити чисті завантаження файлів AJAX, якщо браузер підтримує API файлу - developer.mozilla.org/uk/using_files_from_web_applications
meleyal

Рішення iframe досить просте і просте в роботі
Matthew Lock

це досить стара відповідь, але вона була трохи оманливою. IE підтримував XHR споконвічно ще в IE7 і підтримував його через ActiveX аж до IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp . Практичним способом зробити це було, звичайно, націлювання на спалахи (ударні хвилі) компонентів, або викрутка Flash / ActiveX (Silverlight) управління. Якщо ви можете створити запит і обробити відповідь через javascript, це ajax .., хоча, сказавши це, ajax є синонімом xhr, але він сам не описує механізм / компоненти компонентів, які доставляють / обмінюють корисний навантаження.
Бретт Касвелл

4
@BrettCaswell Я не говорив, що AJAX / XHR неможливий, тільки що неможливо було розмістити файл з ними на старих - але вічних версіях IE. Це було і залишається повністю правдою.
Олі

Це не так, це думка про UX - можливо, це справедливо.
Nimjox

112

Я рекомендую використовувати плагін Fine Uploader для цієї мети. Ваш JavaScriptкод буде:

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

Він використовує JSON - тому для старої версії PHP це буде неможливе використання.
Лоренцо Мануччі

Здається, набагато чіткіше, ніж завантаження файлів Ajax, де мені потрібно включити величезний фрагмент коду просто для того, щоб використати прокляту річ.
ripper234

Новіша URL-версія для версії 2 тепер
Simon East

35
"Цей плагін відкритий за допомогою GNU GPL 2 або новішої версії та GNU LGPL 2 або пізнішої." Тому поки ви не поширюєте копію чи модифіковану версію, вам не доведеться відкривати проект.
Трантор Лю

Я щось пропускаю? Здається, ця бібліотека більше не використовує jquery, тому вона не підтримує синтаксис відповіді?
Джеймс Маккормак

102

Примітка. Ця відповідь застаріла, тепер можна завантажувати файли за допомогою XHR.


Не можна завантажувати файли за допомогою XMLHttpRequest (Ajax). Ви можете імітувати ефект за допомогою iframe або Flash. Відмінний плагін форми jQuery, який розміщує ваші файли через iframe, щоб отримати ефект.


1
Так, ви можете POST на iframe та захопити файл там. У мене з цим дуже обмежений досвід, тому я не можу це коментувати.
Маттіас

15
Невелике зауваження: в останніх версіях Chrome і Firefox можна, stackoverflow.com/questions/4856917 / ...
Alleo

Не підтримується в IE9 і менше
Radmation

96

Підбивання майбутніх читачів.

Асинхронне завантаження файлів

За допомогою HTML5

Ви можете завантажувати файли за допомогою jQuery за допомогою $.ajax()методу, якщо підтримуються FormData та API файлу (обидві функції HTML5).

Ви також можете надсилати файли без FormData, але в будь-якому випадку API файлу повинен бути присутнім для обробки файлів таким чином, що вони можуть бути надіслані за допомогою 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!");
});

Для швидкого, чистого прикладу JavaScript ( без jQuery ) див. " Надсилання файлів за допомогою об'єкта FormData ".

Відступати

Якщо HTML5 не підтримується (немає файлового API ), єдиним іншим чистим рішенням JavaScript (без Flash або будь-якого іншого плагіна браузера) є прихована техніка iframe , яка дозволяє емулювати асинхронний запит без використання об’єкта XMLHttpRequest .

Він складається з встановлення iframe як цілі форми з файловими входами. Коли користувач подає запит, робиться запит і завантажуються файли, але відповідь відображається всередині iframe замість повторного відтворення головної сторінки. Приховування iframe робить весь процес прозорим для користувача та імітує асинхронний запит.

Якщо це зроблено правильно, він повинен працювати практично в будь-якому браузері, але в ньому є деякі застереження, як отримати відповідь від iframe.

У цьому випадку ви можете скористатися плагіном для обгортки на зразок Bifröst, який використовує техніку iframe, але також забезпечує транспорт jQuery Ajax, що дозволяє надсилати файли саме таким $.ajax()методом:

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

Плагіни

Bifröst - це лише невелика обгортка, яка додає підтримку резервного копіювання до ajax методу jQuery, проте багато згаданих плагінів, такі як плагін jQuery Form або завантаження файлів jQuery, включають весь стек від HTML5 до різних резервних копій та деякі корисні функції, щоб полегшити процес. Залежно від ваших потреб і вимог, ви можете розглянути можливість виконання або будь-який з цих плагінів.


3
Одне зауваження, виходячи з документації: ви також повинні відправити contentType: false. Коли я не надсилав це з хромом, тип вмісту форми був недійсним jQuery.
попіл

Гарна відповідь. Кілька пропозицій щодо вдосконалення: видаліть частини коду, не пов’язані з відповіддю, наприклад, зворотній зв'язок .done()та .fail()виклики. Крім того, приклад без використання FormDataта переліку плюсів / мінусів був би приголомшливим.
Zero3

Я отримав цю помилку:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
підсвічник

85

Цей AJAX файл завантаження jQuery плагін завантажує файл який-небудь і передає відповідь на зворотний дзвінок, нічого іншого.

  • Це не залежить від конкретного HTML, просто дайте йому <input type="file">
  • Він не вимагає, щоб ваш сервер відповідав яким-небудь конкретним чином
  • Не має значення, скільки файлів ви використовуєте або де вони знаходяться на сторінці

- Використовуйте якнайменше -

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

- або стільки, скільки -

$('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?
Йордан Фельдштейн

62

Я використовую наведений нижче сценарій для завантаження зображень, які, здається, працюють добре.

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

Пояснення

Я використовую відповідь div щоб показати анімацію завантаження та відповідь після завершення завантаження.

Найкраще - ви можете надсилати додаткові дані, такі як ідентифікатори та ін. Разом з файлом, коли ви використовуєте цей сценарій. Я згадую це extra-dataяк у сценарії.

На рівні PHP це працюватиме як звичайне завантаження файлів. додаткові дані можуть бути отримані як $_POSTдані.

Тут ви не використовуєте плагін та ін. Ви можете змінити код за своїм бажанням. Ви не сліпо кодуєте тут. Це основна функціональність будь-якого завантаження файлів jQuery. Насправді Javascript.


5
-1 для використання jQuery, а не для використання механізму селектора та обробників подій. addEventListenerне є крос-браузером.
Марк

3
Тому що було б безглуздо додавати окрему відповідь, яка б здебільшого грунтувалася на цій, лише з кількома змінами. Натомість цю відповідь слід виправити.
Марк

2
@RainFromHeaven, будь ласка, чи можете ви редагувати відповідь? Я не знаю, як це зробити крос-браузерним способом.
Тіаго Негрі

2
Ще не працює в IE 9 і нижче. Багато користувачів все ще використовують ці версії IE.
П’єр

1
Чи можете мені хтось пояснити, як це можна змусити працювати на asp.net? Чи потрібно використовувати веб-метод? Якщо так, як би це виглядало?
SamuraiJack

49

Ви можете зробити це у ванільному JavaScript досить легко. Ось фрагмент мого поточного проекту:

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: Вибачте, я також повинен був розмістити цей біт. Я просто використовував нову функцію перетягування в HTML5; ви можете знайти приклад тут: html5demos.com/file-api#view-source - просто натисніть "переглянути джерело". По суті, всередині ondropзаходу, який ви можете зробитиvar file = e.dataTransfer.files[0]
30

Можливо, питання було відредаговано, але деякі люди на дискусії, яку я розпочав, я подумав, що відповідь ванільної JS поза темою, якщо ОП запитує рішення jQuery (за умови наявності такого) і такі відповіді належать до окремого питання.
Енді

4
@Andy Ну, я не згоден, і, схоже, 34 інші теж роблять. Якщо ви можете використовувати jQuery, то ви, звичайно, можете використовувати JavaScript. У будь-якому випадку, це сайт громади - я намагаюся тут допомогти не лише ОП. Кожен вільний вибирати / використовувати відповідь, який їм найбільше подобається. Деякі люди просто тяжіють до jQuery, тому що вони думають, що це буде набагато простіше / менше рядків коду, коли насправді їм взагалі не потрібні накладні витрати на додаткову бібліотеку.
mpen

47

Ви можете просто завантажити 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 тільки jQuery.
Зайн Алі

як досягти прогресу завантаження?
Алі Шерафат

44

Найпростіший і надійний спосіб, який я робив це в минулому, - це просто націлити на прихований тег iFrame вашою формою - тоді він подаватиметься в рамках iframe, не завантажуючи сторінку.

Тобто, якщо ви не хочете використовувати плагін, JavaScript або будь-які інші форми "магії", крім HTML. Звичайно, ви можете комбінувати це з JavaScript або з тим, що у вас є ...

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

Ви також можете прочитати вміст iframe onLoad для помилок сервера або відповіді на успіх, а потім вивести його користувачеві.

Chrome, iFrames та onLoad

-умітка - читати потрібно лише тоді, коли вас цікавить, як налаштувати блокатор інтерфейсу користувача під час завантаження / завантаження

Наразі Chrome не запускає подію onLoad для iframe, коли він використовується для передачі файлів. Firefox, IE та Edge запускають події завантаження для передачі файлів.

Єдиним рішенням, яке знайшов роботу для Chrome, було використання файлу cookie.

Зробити це в основному при запуску / завантаженні:

  • [Сторона клієнта] Почніть інтервал, щоб шукати печиво
  • [Сторона сервера] Зробіть все, що вам потрібно, з даними файлу
  • [Server Side] Встановлення файлу cookie для інтервалу на стороні клієнта
  • [Client Side] Interval бачить файл cookie та використовує його як подію onLoad. Наприклад, ви можете запустити блокатор користувальницького інтерфейсу, а потім OnLoad (або коли буде створено файл cookie) видалити блокатор інтерфейсу користувача

Використання файлу cookie для цього некрасиво, але воно працює.

Я створив плагін jQuery, щоб вирішити цю проблему для Chrome під час завантаження, його можна знайти тут

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

Той самий основний принцип стосується і завантаження.

Щоб використовувати завантажувач (очевидно, включайте 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');
 });

І на стороні сервера, безпосередньо перед передачею файлових даних, створіть файл cookie

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

Плагін побачить файл cookie, а потім запустить onCompleteзворотний виклик.


3
Я це люблю. Якби хтось міг згадати потенційні проблеми цього геніального рішення. Я насправді не розумію, чому люди перекручують і використовують ці незграбні бібліотеки та плагіни, коли є рішення.
Євген Афанасьєв

1
Я думаю, що причиною було б показати деяку інформацію про хід під час завантаження.
Прахар Мішра

32

Я знайшов рішення, щоб <form>ціль приховувала iFrame. Потім iFrame може запустити JS, щоб показати користувачеві, що він завершений (на завантаженні сторінки).


1
Мене цікавить ця відповідь, чи є у вас демонстрація, з якою ви можете зв’язатись?
lfender6445

32

Я написав це в середовищі Rails . Це лише п’ять рядків JavaScript, якщо ви використовуєте легкий плагін jQuery-форми.

Завдання полягає в тому, щоб AJAX завантажував роботу, оскільки стандарт remote_form_forне розуміє подання форми в декількох частинах. Він не збирається надсилати файлові дані Rails звертається назад із запитом AJAX.

Ось тут вступає в дію плагін jQuery-форми.

Ось код Rails для цього:

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

Ось пов'язаний 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.
  },
 });
});

А ось дія контролера Rails, досить ванільна:

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

Я використовую це протягом останніх кількох тижнів з Bloggity, і це працювало як чемпіон.


31

Простий завантажувач Ajax - це ще один варіант:

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

  • Крос-браузер - працює в IE7 +, Firefox, Chrome, Safari, Opera
  • Підтримує кілька одночасних завантажень - навіть у браузерах, що не входять до HTML5
  • Немає спалаху чи зовнішньої CSS - лише один файл Javascript 5 Кб
  • Необов’язкова вбудована підтримка повністю перехресних панелей прогресу веб-браузера (з використанням розширення APC PHP)
  • Гнучка та настроювана - використовуйте будь-який елемент як кнопку завантаження, стилюйте власні показники прогресу
  • Форми не потрібні, просто надайте елемент, який буде служити кнопкою завантаження
  • Ліцензія MIT - безкоштовно використовувати в комерційних проектах

Приклад використання:

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
Це , як видається, найбільш перспективним до сих пір, ви мали мене в IE7+! Спробуйте зараз. Спасибі
П'єру

25

jQuery Uploadify - ще один хороший плагін, який я використовував раніше для завантаження файлів. Код JavaScript настільки ж простий, як і наступний: код. Однак нова версія не працює в 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) {
        // ...
    }
});

Я зробив багато пошуків, і я прийшов до іншого рішення для завантаження файлів без будь-якого плагіна і тільки з ajax. Рішення наступне:

$(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 мертвий роками. Більше не підтримується і не підтримується.
Рей Ніколус

24

Ось лише ще одне рішення, як завантажити файл ( без будь-якого плагіна )

Використання простих Javascripts та AJAX (з смугою прогресу)

Частина 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>

Частина 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";
}

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

Ось додаток ПРИКЛАД


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

Ви можете використовувати дані форми, щоб розмістити всі свої значення, включаючи зображення.


6
Примітка: cache: falseнадлишок у POSTзапиті, оскільки POST ніколи не кешується.
Пройшов кодування

@Vivek Aasaithambi, я отримав цю помилку:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
підсвічник

15

Щоб завантажити файл асинхронно за допомогою Jquery, виконайте наведені нижче дії:

крок 1 У вашому проекті відкрийте Nuget Manager та додайте пакет (jquery fileupload (лише вам потрібно записати його в поле пошуку, він з’явиться та встановити його)) URL: https://github.com/blueimp/jQuery-File- Завантажити

крок 2 Додайте нижче сценарії в HTML-файли, які вже додані до проекту, виконавши вище пакета:

jquery.ui.widget.js

jquery.iframe-transport.js

jquery.fileupload.js

крок 3 Запишіть керування завантаженням файлу відповідно до наведеного нижче коду:

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

крок 4 запишіть метод js як uploadFile, як показано нижче:

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

        };

крок 5 У готовому файлі елемента виклику функціональної функції виклику для запуску процесу, як описано нижче:

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

});

крок 6 Напишіть контролер MVC та дії, як зазначено нижче:

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

Сучасний підхід без Jquery полягає у використанні об'єкта FileList, з якого ви повертаєтесь, <input type="file">коли користувач вибирає файл (и), а потім використовувати " Вибір", щоб розмістити файл File List, обведений навколо об'єкта 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
    });
});

Мабуть, не підтримується в IE
Marco Demaio

11

Ви можете побачити , що вирішується рішення з робочим демо тут , що дозволяє переглядати і представляти файли форми на сервер. Для вашого випадку вам потрібно використовувати Ajax для полегшення завантаження файлів на сервер:

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

Надані дані є форматом. У jQuery використовуйте функцію надсилання форми замість натискання кнопки, щоб надіслати файл форми, як показано нижче.

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

     });
   });
});

Переглянути більш детальну інформацію


11

Зразок: Якщо ви використовуєте jQuery, ви можете легко зробити файл для завантаження. Це невеликий і міцний плагін jQuery, http://jquery.malsup.com/form/ .

Приклад

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

Я сподіваюся, що це буде корисно


10

Можна використовувати

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

Демо


9

Перетворіть файл у base64 за допомогою | HTML5's readAsDataURL () або якогось базового кодера . Скрипаль тут

var reader = new FileReader();

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

        reader.readAsBinaryString(file);

Потім для завантаження:

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

9

Ви можете передавати додаткові параметри разом з іменем файлу при здійсненні асинхронного завантаження за допомогою XMLHttpRequest (без залежності спалаху та рамки). Додайте додаткове значення параметра за допомогою FormData та надішліть запит на завантаження.


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

Також завантаження файлів інтерфейсу інтерфейсу JavaScript Syncfusion забезпечує рішення для цього сценарію, просто використовуючи аргумент події. Ви можете знайти тут документацію та додаткові відомості про цей контроль. Тут введіть опис посилання


8

Шукайте Поводження з процесом завантаження файлу асинхронно тут: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Зразок за посиланням

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

Це моє рішення.

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

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

Контролер

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

2
Ви ніби змішали якусь рамку у своїй відповіді. Вам, принаймні, слід згадати, для яких рамків можна відповісти. Ще краще, видаліть усі рамки та надайте лише відповідь на поставлене запитання.
Zero3

2
так що насправді є рамка mvc, яка називається "mvc"? і він використовує синтаксис csharpish? це жорстоко.
нечіп

6

За допомогою HTML5 та JavaScript , завантаження async є досить простим, я створюю логіку завантаження разом із вашим html. Це не працює повністю, як це потрібно api, але демонструю, як це працює, якщо у вас є кінцева точка, викликана /uploadз кореня вашого веб-сайту, цей код повинен працювати для вас:

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>

Також додаткова інформація про XMLHttpReques:

Об'єкт XMLHttpRequest

Усі сучасні браузери підтримують об’єкт XMLHttpRequest. Об'єкт XMLHttpRequest можна використовувати для обміну даними з веб-сервером за кадром. Це означає, що можна оновити частини веб-сторінки, не перезавантажуючи всю сторінку.


Створіть об'єкт XMLHttpRequest

Усі сучасні браузери (Chrome, Firefox, IE7 +, Edge, Safari, Opera) мають вбудований об’єкт XMLHttpRequest.

Синтаксис для створення об'єкта XMLHttpRequest:

змінна = новий XMLHttpRequest ();


Доступ через усі домени

З міркувань безпеки сучасні веб-переглядачі не дозволяють отримувати доступ через домени.

Це означає, що і веб-сторінка, і файл XML, який вона намагається завантажити, повинні бути розташовані на одному сервері.

У прикладах для W3Schools відкриті файли XML, розташовані в домені W3Schools.

Якщо ви хочете використовувати приклад вище на одній із своїх власних веб-сторінок, файли XML, які ви завантажуєте, повинні знаходитись на вашому власному сервері.

Детальніше ви можете продовжити читати тут ...


5

Ви можете використовувати новіший API Fetch за допомогою JavaScript. Подобається це:

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

Перевага: API Fetch підтримується всіма сучасними браузерами, тому вам нічого не потрібно імпортувати. Також зауважте, що fetch () повертає Promise, який потім обробляється за допомогою .then(..code to handle response..)асинхронного використання .


4

Ви можете робити асинхронні множинні завантаження файлів за допомогою JavaScript або jQuery і до цього, не використовуючи жодного плагіна. Ви також можете показувати хід завантаження файлів у режимі реального часу в контролі прогресу. Я натрапив на 2 приємні посилання -

  1. Функція завантаження файлів Mulitple на базі веб-форм ASP.NET на панелі прогресу
  2. Кілька завантажених файлів на базі ASP.NET MVC зроблено в jQuery

Мовою стороні сервера є C #, але ви можете внести деякі зміни для того, щоб він працював з іншою мовою, як PHP.

Завантаження файлу ASP.NET Core MVC:

У Перегляді створити контроль завантаження файлів у HTML:

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

Тепер створіть метод дії у своєму контролері:

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

Змінна hostingEnvironment має тип IHostingEnvironment, який можна вводити в контролер за допомогою введення залежності, наприклад:

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

Чи можете ви включити у відповідь суть рішення, оскільки в іншому випадку це може стати марним, якщо пов’язаний веб-сайт зміниться або перейде в режим офлайн.
Діма Кожевін

4

Для PHP шукайте 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

Ви також можете використати щось на зразок https://uppy.io .

Він завантажує файли, не відходячи від сторінки та пропонує кілька бонусів, як перетягування та перетягування, відновлення завантаження у випадку збоїв браузера / невдалої мережі та імпортування, наприклад, з Instagram. Це відкритий код і не покладається на jQuery / React / Angular / Vue, але з ним можна використовувати. Відмова: як її творець я упереджений;)


Посилання вище мертве. Ось github: github.com/transloadit/uppy
Кріс Чарльз

uppy.io - це резервне копіювання сторінок CloudFlare + GitHub і для мене? Ще корисно мати пряме посилання на репо, хоча :)
kvz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.