Как я могу загружать файлы асинхронно?

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 File Uploader - Плагин для загрузки нескольких файлов - Мини-загрузка нескольких файлов - Загрузка файлов jQuery Вы можете искать другие проекты в NPM (используя «jquery-plugin» в качестве ключевого слова) или в Github.
Веселый
72
вы получаете только имя файла, потому что ваше имя файла var получает значение $ ('# file'), а не файл, который лежит на входе
Jimmy
21
Вот хороший пример : http://blueimp.github.io/jQuery-File-Upload/ - Загрузка ajax HTML5 - Изящный откат к фреймам для неподдерживаемых браузеров - Асинхронная загрузка нескольких файлов Мы использовали это, и он отлично работает. ( Документация здесь )
Ashish Panery
3
Также проверьте это: stackoverflow.com/questions/6974684/… , здесь объясняется, как этого добиться с помощью jQuery
Chococroc
2
@ Джимми Как он мог получить файл, который лежит вместо ввода?
Алекс

Ответы:

2519

С HTML5 вы можете загружать файлы с помощью Ajax и jQuery. Мало того, вы можете выполнять проверку файлов (имя, размер и тип MIME) или обрабатывать событие progress с помощью тега прогресса HTML5 (или div). Недавно мне пришлось сделать загрузчик файлов, но я не хотел использовать 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 доступны не во всех браузерах.

olanod
источник
14
Могу ли я использовать $ _FILES в upload.php?
Алессандро Косентино
71
Это должно работать в Internet Explorer, но только в версии 10. ( caniuse.com/xhr2 )
Тайлер
18
Привет, я ценю, что PHP - ваш любимый язык ... но мне интересно, знаете ли вы, работает ли он также в ASP.NET MVC? Я разработчик .NET, и я пытался использовать ваш простой пример для загрузки некоторых файлов AJAX, но на серверной стороне я не получаю файл, который я разместил через AJAX. Я использую последний Chrome.
Шуми
25
Это FormData, который делает всю магию здесь. Не забудьте проверить эти документы - он охватывает все ваши вопросы о нескольких файлах и полях.
воплощен
4
Просто чтобы кто-то другой не тратил часы ... name="file"это очень важно <input>для тега file, если вы собираетесь использовать данные в PHP (и, возможно, в других местах). Я создал форму динамически, используя javascript, поэтому мне не понадобился атрибут name, но я выяснил, каким сложным образом он вам нужен для получения данных на стороне сервера.
Кивак Вольф
273

Обновление 2019 года: все еще зависит от браузеров, которые вы используете.

С «новым» HTML5 fileAPI важно понять, что он не поддерживается до IE 10 . Если конкретный рынок, на который вы ориентируетесь, имеет склонность выше средних к старым версиям Windows, у вас может не быть к нему доступа.

По состоянию на 2017 год около 5% браузеров - это IE 6, 7, 8 или 9. Если вы идете в большую корпорацию (например, это инструмент B2B или то, что вы предоставляете для обучения), это число может взлететь , В 2016 году я имел дело с компанией, использующей IE8, на более чем 60% своих машин.

Сейчас 2019 год, почти 11 лет после моего первоначального ответа. IE9 и ниже глобально около отметки 1%, но все еще есть кластеры более высокого использования.

Важным выводом из этого - какой бы ни была функция - является проверка того , какой браузер используют ваши пользователи . Если вы этого не сделаете, вы извлечете быстрый и мучительный урок о том, почему «работает для меня» недостаточно хорошо в доставке клиенту. могу ли я использовать - полезный инструмент, но обратите внимание, откуда они свою демографию. Они могут не совпадать с вашими. Это никогда не является правдой, чем корпоративная среда.

Мой ответ от 2008 года следует.


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

Это «настоящий» пост, поэтому он не совсем интерактивный. Если вам нужен статус, вам нужно что-то на стороне сервера для обработки этого. Это сильно зависит от вашего сервера. ASP.NET имеет более приятные механизмы. PHP не работает, но вы можете использовать Perl модификации или Apache, чтобы обойти это.

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

Или используйте решение Java / Flash. Они намного более гибки в том, что они могут делать со своими постами ...

Oli
источник
142
Напомним,
Решение iframe довольно простое, и с ним легко начать работать
Мэтью Локк
это довольно старый ответ, но он немного вводил в заблуждение. IE изначально поддерживал XHR еще в IE7 и поддерживал его через ActiveX вплоть до IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp . Практическим способом сделать это, безусловно, было нацеливание на компоненты flash (ударная волна) или развертывание элемента управления 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);
    }
  });
});
Shiladitya
источник
Он использует JSON - поэтому для старой версии PHP это будет невозможно.
Лоренцо Мануччи
Кажется, намного чище, чем Ajax File Upload, где мне нужно включить огромный кусок кода, чтобы использовать эту чертову штуку.
ripper234
Более новый
Саймон Ист
35
«Этот плагин с открытым исходным кодом под GNU GPL 2 или более поздней версии и GNU LGPL 2 или более поздней». Поэтому, пока вы не распространяете копию или измененную версию, вам не нужно открывать свой проект.
Трантор Лю
Я что-то пропустил? Кажется, эта библиотека больше не использует jquery, поэтому она не поддерживает синтаксис из ответа?
Джеймс МакКормак
102

Примечание. Этот ответ устарел, теперь можно загружать файлы с помощью XHR.


Вы не можете загружать файлы, используя XMLHttpRequest (Ajax). Вы можете смоделировать эффект, используя iframe или Flash. Отличный плагин jQuery Form, который отправляет ваши файлы через iframe, чтобы получить эффект.

Маттиас
источник
1
Да, вы можете POST в iframe и захватить файл там. У меня очень ограниченный опыт в этом, поэтому я не могу комментировать это.
Маттиас
15
Небольшое замечание: в последних версиях Chrome и Firefox это возможно, stackoverflow.com/questions/4856917/…
Alleo
Не поддерживается в IE9 и менее
Radmation
96

Подведение итогов для будущих читателей.

Асинхронная загрузка файлов

С HTML5

Вы можете загружать файлы с помощью jQuery, используя $.ajax()метод if FormData и File 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 не поддерживается (без File 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 - это просто небольшая оболочка, которая добавляет поддержку отката в метод jjuery ajax, но многие из вышеупомянутых плагинов, такие как плагин jQuery Form или jQuery File Upload, включают целый стек из HTML5 для различных откатов и некоторые полезные функции для облегчения процесса. В зависимости от ваших потребностей и требований вы можете рассмотреть пустую реализацию или один из этих плагинов.

404
источник
3
На что следует обратить внимание, основываясь на документации: вы также должны отправить contentType: false. Когда я не отправил это с Chrome, тип содержимого формы был признан недействительным jQuery.
Ясень
Хороший ответ. Несколько предложений по улучшению: Удалите части кода , не связанных с ответом, например, .done()и .fail()обратных вызовов. Кроме того, пример без использования FormDataи список плюсов / минусов был бы потрясающим.
Ноль3
Я получил эту ошибку:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
подсвечник
85

Этот плагин JQuery для загрузки AJAX-файлов загружает файл где-то и передает ответ на обратный вызов, ничего больше.

  • Это не зависит от конкретного 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? Я использую webmethod? Если да, то как бы это выглядело?
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);
mpen
источник
3
@Gary: Извините, я должен был опубликовать этот бит тоже. Я просто использовал новую функциональность перетаскивания в HTML5; Вы можете найти пример здесь: html5demos.com/file-api#view-source - просто нажмите «Просмотр источника». По сути, внутри ondropмероприятия вы можете сделатьvar file = e.dataTransfer.files[0]
mpen
Возможно, вопрос был отредактирован с тех пор, но некоторые люди в открытой дискуссии, которую я открыл, считают, что ванильный ответ JS не по теме, если OP запрашивает решение 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 запускают событие onload для передачи файлов.

Единственным решением, которое я нашел для Chrome, было использование куки.

Чтобы сделать это в основном, когда начата загрузка / выгрузка:

  • [Клиентская сторона] Начать интервал, чтобы искать наличие куки
  • [Server Side] Делайте все, что вам нужно с данными файла
  • [Server Side] Установить cookie для клиентского интервала
  • [Сторона клиента] Интервал видит cookie и использует его как событие onLoad. Например, вы можете запустить блокировщик пользовательского интерфейса, а затем onLoad (или при создании 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, "/");

Плагин увидит куки, а затем вызовет onCompleteобратный вызов.

ArtisticPhoenix
источник
3
Я люблю это. Если бы кто-то мог упомянуть потенциальные проблемы с этим блестящим решением. Я действительно не понимаю, почему люди пишут и используют эти неуклюжие библиотеки и плагины, когда есть решение.
Евгений Афанасьев
1
Ну, я думаю, причина в том, чтобы показать некоторую информацию о прогрессе при загрузке.
Прахар Мишра
32

Решение, которое я нашел, состояло в том, чтобы у <form>цели был скрытый кадр. Затем iFrame может запустить JS, чтобы показать пользователю, что он завершен (при загрузке страницы).

Дэррил Хейн
источник
1
меня интересует этот ответ, у вас есть демоверсия, на которую вы можете сослаться?
lfender6445
32

Я написал это в среде Rails . Это всего лишь пять строк JavaScript, если вы используете легкий плагин jQuery-form.

Задача состоит в том, чтобы загрузить 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, и он работал как чемпион.

wbharding
источник
31

Простой Ajax Uploader - это еще один вариант:

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

  • Кросс-браузер - работает в IE7 +, Firefox, Chrome, Safari, Opera
  • Поддержка нескольких одновременных загрузок - даже в браузерах, отличных от HTML5
  • Нет флэш-памяти или внешнего CSS - только один 5Kb файл Javascript
  • Дополнительная встроенная поддержка полностью кросс-браузерных индикаторов прогресса (с использованием PHP-расширения APC)
  • Гибкость и широкие возможности настройки - используйте любой элемент в качестве кнопки загрузки, используйте собственные индикаторы прогресса
  • Не требуется никаких форм, просто предоставьте элемент, который будет служить кнопкой загрузки
  • Лицензия 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
    }
});
user1091949
источник
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 и добавьте пакет (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
                };


        }

    }
Ashish
источник
14

Современный подход без Jquery состоит в том, чтобы использовать объект FileList, который вы получаете, <input type="file">когда пользователь выбирает файл (-ы), а затем использовать Fetch для публикации FileList, обернутого вокруг объекта 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
Марко Демайо
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
  }
});

Я надеюсь, что это будет полезно

MEAbid
источник
10

Ты можешь использовать

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

демонстрация

Amit
источник
9

Конвертируйте файл в base64, используя readAsDataURL () HTML5 или какой- либо кодировщик base64 . Скрипка здесь

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);
тнт-Rox
источник
9

Вы можете передать дополнительные параметры вместе с именем файла при выполнении асинхронной загрузки с использованием XMLHttpRequest (без зависимости flash и iframe). Добавьте значение дополнительного параметра с помощью 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
});

Кроме того, загрузка файла интерфейса пользователя Syncfusion JavaScript предоставляет решение для этого сценария, просто используя аргумент события. вы можете найти документацию здесь и более подробную информацию об этом элементе управления здесь, введите описание ссылки здесь

Картик Равичандран
источник
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
Вы, кажется, смешали какую-то структуру в свой ответ. Вы должны, по крайней мере, указать, для какой структуры ваш ответ пригоден для использования. А еще лучше, удалите все элементы фреймворка и представьте только ответ на поставленный вопрос.
Ноль3
2
так что на самом деле фреймворк MVC называется "MVC"? и он использует синтаксис csharpish? это жестоко
nonchip
6

Используя HTML5 и JavaScript , выгрузка асинхронных файлов довольно проста, я создаю логику выгрузки вместе с вашим 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

Вы можете использовать более новый Fetch API с помощью 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));
}                               

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

Бороды
источник
4

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

  1. Функция многократной загрузки файлов на основе веб-форм 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