У меня есть приложение javascript, которое отправляет запросы POST ajax на определенный URL. Ответ может быть строкой JSON или файлом (в виде вложения). Я легко могу определить Content-Type и Content-Disposition в своем вызове ajax, но как только я обнаружу, что ответ содержит файл, как я могу предложить клиенту загрузить его? Я прочитал несколько похожих тем здесь, но ни одна из них не дает ответ, который я ищу.
Пожалуйста, пожалуйста, пожалуйста, не публикуйте ответы, предлагающие мне не использовать ajax для этого или что я должен перенаправить браузер, потому что ничего из этого не вариант. Использование простой HTML-формы также не вариант. Мне нужно показать клиенту диалог загрузки. Можно ли это сделать и как?
javascript
jquery
ajax
Павле Предич
источник
источник
Ответы:
Создайте форму, используйте метод POST, отправьте форму - нет необходимости в iframe. Когда страница сервера отвечает на запрос, напишите заголовок ответа для mime-типа файла, и он откроет диалоговое окно загрузки - я делал это несколько раз.
Вы хотите контент-приложение / загрузку - просто найдите, как обеспечить загрузку для любого языка, который вы используете.
источник
Не сдавайтесь так быстро, потому что это можно сделать (в современных браузерах), используя части FileAPI:
Вот старая версия с использованием jQuery.ajax. Он может искажать двоичные данные, когда ответ преобразуется в строку некоторой кодировки.
источник
document.body.removeChild(a);
var blob =this.responce; /** if (typeof File === 'function') { try { blob = new File([this.response], filename, { type: type }); } catch (e) { /* Edge */ } } if (typeof blob === 'undefined') { blob = new Blob([this.response], { type: type }); } */
window.location.href = downloadUrl
вместоwindow.location = downloadUrl
Я столкнулся с той же проблемой и успешно решил ее. Мой вариант использования это.
« Отправьте данные JSON на сервер и получите файл Excel. Этот файл Excel создается сервером и возвращается как ответ клиенту. Загрузите этот ответ как файл с пользовательским именем в браузере »
Вышеуказанный фрагмент просто делает следующее
Здесь нам нужно тщательно настроить несколько вещей на стороне сервера. Я установил несколько заголовков в Python Django HttpResponse. Вам необходимо установить их соответствующим образом, если вы используете другие языки программирования.
Так как я загружаю xls (excel) здесь, я настроил contentType выше одного. Вам нужно установить его в соответствии с вашим типом файла. Вы можете использовать эту технику для загрузки любых файлов.
источник
Какой серверный язык вы используете? В моем приложении я могу легко загрузить файл из вызова AJAX, установив правильные заголовки в ответе PHP:
Установка заголовков на стороне сервера
Это фактически «перенаправит» браузер на эту страницу загрузки, но, как сказал @ahren alread в своем комментарии, он не уйдет с текущей страницы.
Все дело в настройке правильных заголовков, поэтому я уверен, что вы найдете подходящее решение для используемого на стороне сервера языка, если это не PHP.
Обработка ответной стороны клиента
Предполагая, что вы уже знаете, как сделать вызов AJAX, на стороне клиента вы выполняете запрос AJAX к серверу. Затем сервер генерирует ссылку, откуда этот файл может быть загружен, например, «прямой» URL, на который вы хотите указать. Например, сервер отвечает:
При обработке ответа вы вставляете
iframe
в свое тело и устанавливаете дляiframe
SRC URL-адрес, который вы только что получили, вот так (используя jQuery для простоты этого примера):Если вы установили правильные заголовки, как показано выше, iframe вызовет диалог загрузки без перехода браузера от текущей страницы.
Запись
Дополнительное дополнение по вашему вопросу; Я думаю, что лучше всегда возвращать JSON при запросе материала с технологией AJAX. После получения ответа JSON вы можете решить, что с ним делать на стороне клиента. Может быть, например, позже вы захотите, чтобы пользователь щелкнул ссылку для загрузки на URL-адрес, а не заставлял загрузку напрямую, в вашей текущей настройке вам придется обновить как клиентскую, так и серверную сторону, чтобы сделать это.
источник
Для тех, кто ищет решение с угловой точки зрения, это сработало для меня:
источник
link.download = ""
приводит к случайному имени файла guid, иlink.download = null
приводит к файлу с именем "null".INPUT
элементаHTMLInputElement.files
. См . Документацию MDN для ввода файла для более подробной информации.Вот как у меня это работает https://stackoverflow.com/a/27563953/2845977
Обновленный ответ с использованием download.js
источник
success: function (response, status, request) { download(response, "filename.txt", "application/text"); }
Я вижу, вы уже нашли решение, однако я просто хотел добавить некоторую информацию, которая может помочь кому-то, пытающемуся достичь того же самого с большими запросами POST.
У меня была такая же проблема пару недель назад, действительно, невозможно добиться "чистой" загрузки через AJAX, Filament Group создала плагин jQuery, который работает точно так, как вы уже узнали, он называется jQuery File Скачать, однако, есть и обратная сторона этой техники.
Если вы отправляете большие запросы через AJAX (скажем, файлы + 1 МБ), это отрицательно скажется на скорости отклика. В медленных подключениях к Интернету , вам придется ждать много , пока запрос не посылаются , а также ждать файл для загрузки. Это не похоже на мгновенный щелчок "=" "всплывающее окно" => "начало загрузки". Это больше похоже на «щелчок» => «ожидание отправки данных» => «ожидание ответа» => «запуск загрузки», при котором файл выглядит в два раза больше, потому что вам придется ждать отправки запроса через AJAX и вернуть его в виде загружаемого файла.
Если вы работаете с файлами небольшого размера <1 МБ, вы этого не заметите. Но, как я обнаружил в своем собственном приложении, для файлов большего размера это практически невыносимо.
Мое приложение позволяет пользователям экспортировать изображения, сгенерированные динамически, эти изображения отправляются через POST-запросы в формате base64 на сервер (это единственный возможный способ), затем обрабатываются и отправляются пользователям в виде файлов .png, .jpg, base64. Строки для изображений + 1 МБ огромны, это заставляет пользователей ждать больше, чем необходимо, чтобы файл начал загружаться. В медленных интернет-соединениях это может быть действительно раздражающим.
Мое решение для этого состояло в том, чтобы временно записать файл на сервер, когда он будет готов, динамически сгенерировать ссылку на файл в виде кнопки, которая изменяется между состояниями «Пожалуйста, подождите ...» и «Загрузить» и одновременно распечатайте изображение base64 во всплывающем окне предварительного просмотра, чтобы пользователи могли «щелкнуть правой кнопкой мыши» и сохранить его. Это делает все время ожидания более терпимым для пользователей, а также ускоряет процесс.
Обновление 30 сентября 2014 г .:
Пример загрузки скрипта:
Я знаю, что это далеко от того, о чем просил ФП, однако я чувствовал, что было бы неплохо дополнить мой ответ своими выводами. Когда я искал решения для своей проблемы, я прочитал множество веток «Загрузка из данных AJAX POST», которые не дали мне ответ, который я искал, я надеюсь, что эта информация поможет кому-то, стремящемуся достичь чего-то подобного.
источник
jQuery File Download
Только перенаправить меня к ссылке. Я называю это так:jQuery.download("api/ide/download-this-file.php", {filePath: path2Down}, "POST");
.Я хочу указать на некоторые трудности, которые возникают при использовании техники в принятом ответе, то есть при использовании формы сообщения:
Вы не можете установить заголовки по запросу. Если ваша схема аутентификации включает заголовки, Json-Web-Token, переданный в заголовке Authorization, вам нужно будет найти другой способ отправить его, например, в качестве параметра запроса.
Вы не можете точно сказать, когда запрос закончился. Что ж, вы можете использовать cookie, который устанавливается в ответ, как это делает jquery.fileDownload , но это FAR от идеального. Он не будет работать для одновременных запросов и сломается, если ответ так и не поступит.
Если сервер отвечает с ошибкой, пользователь будет перенаправлен на страницу ошибки.
Вы можете использовать только типы контента, поддерживаемые формой . Это означает, что вы не можете использовать JSON.
В итоге я использовал метод сохранения файла на S3 и отправки предварительно подписанного URL-адреса, чтобы получить файл.
источник
Для тех, кто ищет более современный подход, вы можете использовать
fetch API
. В следующем примере показано, как загрузить файл электронной таблицы. Это легко сделать с помощью следующего кода.Я считаю, что этот подход гораздо легче понять, чем другие
XMLHttpRequest
решения. Кроме того, он имеет синтаксис, аналогичныйjQuery
подходу, без необходимости добавления каких-либо дополнительных библиотек.Конечно, я бы посоветовал проверить, для какого браузера вы разрабатываете, так как этот новый подход не будет работать в IE. Вы можете найти полный список совместимых браузеров по следующей [ссылке] [1].
Важное замечание : В этом примере я отправляю запрос JSON серверу, который прослушивает данные
url
. Этоurl
должно быть установлено, на моем примере я предполагаю, что вы знаете эту часть. Также рассмотрите заголовки, необходимые для работы вашего запроса. Поскольку я отправляю JSON, я должен добавитьContent-Type
заголовок и установить егоapplication/json; charset=utf-8
, чтобы сервер знал тип запроса, который он получит.источник
Вот мое решение с использованием временной скрытой формы.
Обратите внимание, что я широко использую JQuery, но вы можете сделать то же самое с нативным JS.
источник
Как уже говорили другие, вы можете создать и отправить форму для загрузки через запрос POST. Однако вам не нужно делать это вручную.
Одна действительно простая библиотека для выполнения именно этого - jquery.redirect . Он предоставляет API, похожий на стандартный
jQuery.post
метод:источник
Это вопрос на 3 года, но у меня была такая же проблема сегодня. Я посмотрел ваше отредактированное решение, но думаю, что оно может принести в жертву производительность, потому что оно должно сделать двойной запрос. Так что если кому-то нужно другое решение, которое не подразумевает повторного вызова службы, то я так и сделал:
Эта форма просто используется для вызова службы и избегает использования window.location (). После этого вам просто нужно отправить форму из jquery, чтобы вызвать сервис и получить файл. Это довольно просто, но таким образом вы можете сделать загрузку с помощью POST . Теперь я понимаю, что это может быть проще, если услуга, которую вы вызываете, является GET , но это не мой случай.
источник
Я использовал этот FileSaver.js . В моем случае с CSV-файлами я сделал это (в coffescript):
Я думаю, что для самого сложного случая данные должны быть обработаны должным образом. Под капотом FileSaver.js реализован тот же подход, что и в ответе Джонатана Аменда .
источник
см .: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ он вернет в качестве ответа большой двоичный объект, который затем может быть помещен в файловую заставку
источник
Чтобы получить ответ Джонатана Аменса на работу в Edge, я внес следующие изменения:
к этому
Я бы предпочел опубликовать это как комментарий, но у меня недостаточно репутации для этого
источник
Вот мое решение, собранное из разных источников: Реализация на стороне сервера:
Реализация на стороне клиента (с использованием jquery):
источник
есть другое решение для загрузки веб-страницы в ajax. Но я имею в виду страницу, которая должна быть сначала обработана, а затем загружена.
Для начала нужно отделить обработку страницы от загрузки результатов.
1) В вызове ajax выполняются только расчеты страницы.
Я надеюсь, что это решение может быть полезным для многих, как и для меня.
источник
Если ответ является буфером массива , попробуйте это в событии onsuccess в Ajax:
источник
Ниже мое решение для загрузки нескольких файлов в зависимости от некоторого списка, который состоит из нескольких идентификаторов и поиска в базе данных, файлы будут определены и готовы к загрузке - если таковые существуют. Я вызываю действие C # MVC для каждого файла, используя Ajax.
И да, как говорили другие, это можно сделать в jQuery Ajax. Я сделал это с успехом Ajax, и я всегда посылаю ответ 200.
Итак, это ключ:
И это мой код:
Тогда звоню:
C # MVC:
Пока вы возвращаете ответ 200, успех в Ajax может работать с ним, вы можете проверить, существует ли файл на самом деле или нет, так как строка в этом случае будет ложной, и вы можете сообщить пользователю об этом:
источник
Мне нужно было решение, подобное @ alain-cruz, но в nuxt / vue с несколькими загрузками. Я знаю, что браузеры блокируют загрузку нескольких файлов, и у меня также есть API, который возвращает набор данных в формате CSV. Сначала я собирался использовать JSZip, но мне нужна была поддержка IE, так что вот мое решение. Если кто-то может помочь мне улучшить это, это было бы здорово, но пока это работает для меня.
API возвращает:
page.vue:
источник