У меня есть действие Struts2 на стороне сервера для загрузки файлов.
<action name="download" class="com.xxx.DownAction">
<result name="success" type="stream">
<param name="contentType">text/plain</param>
<param name="inputName">imageStream</param>
<param name="contentDisposition">attachment;filename={fileName}</param>
<param name="bufferSize">1024</param>
</result>
</action>
Однако, когда я вызываю действие, используя jQuery:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
в Firebug я вижу, что данные извлекаются с помощью двоичного потока . Интересно, как открыть окно загрузки файла, с помощью которого пользователь может сохранить файл локально?
Ответы:
2019 обновление современных браузеров
Такой подход я бы сейчас рекомендовал с несколькими оговорками:
2012 Оригинальный подход jQuery / iframe / Cookie
Bluish абсолютно прав в этом, вы не можете сделать это через Ajax, потому что JavaScript не может сохранять файлы напрямую на компьютер пользователя (из соображений безопасности). К сожалению, указывая главное окно URL-адреса при загрузке файла означает, что у вас мало контроля над тем, что происходит с пользователем при загрузке файла.
Я создал jQuery File Download, который позволяет "Ajax-подобный" опыт загрузки файлов в комплекте с обратными вызовами OnSuccess и OnFailure, чтобы обеспечить лучшее взаимодействие с пользователем. Взгляните на мой пост в блоге об общей проблеме, которую решает плагин, и о некоторых способах ее использования, а также о демонстрации загрузки файла jQuery в действии . Вот источник
Вот простая демонстрация варианта использования с использованием исходного кода плагина с обещаниями. Демонстрационная страница включает в себя множество других, «лучше» UX примеров.
В зависимости от того, какие браузеры вам нужно поддерживать, вы можете использовать https://github.com/eligrey/FileSaver.js/, который обеспечивает более явный контроль, чем метод IFRAME, который использует jQuery File Download.
источник
Никто не опубликовал это решение @ Пекки ... поэтому я опубликую его. Это может помочь кому-то.
Вам не нужно делать это через Ajax. Просто используйте
источник
window.open(<url>, '_blank');
чтобы гарантировать, что загрузка не заменит ваш текущий контент браузера (независимо от заголовка Content-Disposition).POST
запросе.Вы можете с HTML5
Примечание: возвращаемые данные файла ДОЛЖНЫ быть закодированы в base64, поскольку вы не можете JSON кодировать двоичные данные.
В моем
AJAX
ответе у меня есть структура данных, которая выглядит следующим образом:Это означает, что я могу сделать следующее, чтобы сохранить файл через AJAX
Функция base64ToBlob была взята отсюда и должна использоваться в соответствии с этой функцией
Это хорошо, если ваш сервер создает дамп файловых данных для сохранения. Тем не менее, я не совсем понял, как можно реализовать запасной вариант HTML4
источник
a.click()
Не похоже на работу в светлячок ... Любая идея?a
dom для того, чтобы этот код работал и / или удалитьrevokeObjectURL
часть:document.body.appendChild(a)
var bytechars = atob(base64)
выдает ошибкуJavaScript runtime error: InvalidCharacterError
. Я использую Chrome версии 75.0.3770.142, но я не знаю, что здесь не так.1. Независимость от фреймворка: загрузка файла сервлетом в виде вложения
2. Struts2 Framework: действие загрузки файла в виде вложения
Было бы лучше использовать
<s:a>
тег, указывающий с OGNL на URL, созданный с<s:url>
тегом:В вышеупомянутых случаях вам нужно записать заголовок Content-Disposition в ответ , указав, что файл должен быть загружен (
attachment
) и не открыт браузером (inline
). Вам необходимо указать тип контента , и вы можете добавить имя и длину файла (чтобы браузер мог нарисовать реалистичный индикатор выполнения).Например, при загрузке ZIP:
В Struts2 (если вы не используете Action в качестве сервлета, например, хак для прямой потоковой передачи ), вам не нужно напрямую что-либо записывать в ответ; просто используя тип результата потока и его настройку в struts.xml будет работать: Пример
3. Независимость от фреймворка (/ Struts2 framework): открытие файла сервлета (/ Action) внутри браузера
Если вы хотите открыть файл в браузере, вместо загрузки его, Content-disposition должен быть установлен в встроено , но целью не может быть текущее расположение окна; Вы должны настроить таргетинг на новое окно, созданное с помощью javascript,
<iframe>
на странице или новое окно, созданное на лету с «обсужденным» target = "_ blank":источник
too long url
ошибку.Простой способ заставить браузер загружать файл - сделать запрос следующим образом:
Откроется всплывающее окно загрузки браузера.
источник
Я создал небольшую функцию как обходное решение (вдохновленный плагином @JohnCulviner):
Демо с событием клика:
источник
Я столкнулся с той же проблемой и успешно решил ее. Мой вариант использования это.
« Отправьте данные JSON на сервер и получите файл Excel. Этот файл Excel создается сервером и возвращается как ответ клиенту. Загрузите этот ответ как файл с пользовательским именем в браузере »
Вышеуказанный фрагмент просто делает следующее
Здесь нам нужно тщательно настроить несколько вещей на стороне сервера. Я установил несколько заголовков в Python Django HttpResponse. Вам необходимо установить их соответствующим образом, если вы используете другие языки программирования.
Так как я загружаю xls (excel) здесь, я настроил contentType выше одного. Вам нужно установить его в соответствии с вашим типом файла. Вы можете использовать эту технику для загрузки любых файлов.
источник
HTMLAnchorElement.download
, я думаю объединить его с фирменным методом msSaveOrOpenBlob .Хорошо, на основе кода ndpu вот улучшенная (я думаю) версия ajax_download; -
Используйте это как это; -
Параметры отправляются как правильные параметры после ввода, как если бы они поступали с входных данных, а не как строка в кодировке json, как в предыдущем примере.
ПРЕДУПРЕЖДЕНИЕ: будьте осторожны с возможностью переменного введения на этих формах. Там может быть более безопасный способ кодирования этих переменных. В качестве альтернативы созерцайте избежать их.
источник
Uncaught SecurityError: Blocked a frame with origin "http://foo.bar.com" from accessing a frame with origin "null". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match.
@ResourceMapping() public void downloadFile(final ResourceRequest request, final ResourceResponse response, @ModelAttribute("downForm") FormModel model)
но это не работает ..Вот что я сделал, чистый JavaScript и HTML. Не проверял, но это должно работать во всех браузерах.
источник
источник
download
атрибут, поэтому ваш файл в конечном итоге будет иметь имя «Неизвестно»В Rails я делаю это так:
Хитрость в части window.location . Метод контроллера выглядит так:
источник
Используйте
window.open
https://developer.mozilla.org/en-US/docs/Web/API/Window/openНапример, вы можете поместить эту строку кода в обработчик кликов:
Откроется новая вкладка (из-за имени окна _blank), и эта вкладка откроет URL.
Ваш код на стороне сервера также должен иметь что-то вроде этого:
Таким образом, браузер должен предлагать пользователю сохранить файл на диск, а не просто показывать им файл. Он также автоматически закроет вкладку, которую он только что открыл.
источник
Я пытаюсь загрузить файл CSV, а затем сделать что-то после завершения загрузки. Поэтому мне нужно реализовать соответствующую
callback
функцию.Использование
window.location="..."
не является хорошей идеей, потому что я не могу управлять программой после окончания загрузки. Как-то так, измени заголовок, чтобы он не был хорошей идеей.fetch
хорошая альтернатива, однако она не может поддерживать IE 11 . Иwindow.URL.createObjectURL
не может поддерживать IE 11. Вы можете сослаться на это .Это мой кодекс, он похож на кодекс Шахрукха Алама. Но вы должны позаботиться о том, чтобы,
window.URL.createObjectURL
возможно, создать утечки памяти. Вы можете сослаться на это . После получения ответа данные будут сохранены в памяти браузера. Поэтому, прежде чем нажать наa
ссылку, файл был загружен. Это означает, что вы можете сделать что-нибудь после загрузки.источник
Как ЗАГРУЗИТЬ файл после получения AJAX
Это удобно, когда файл создается долго и нужно показывать PRELOADER
Пример при отправке веб-формы:
Необязательный функционал закомментирован для упрощения примера.
Не нужно создавать временные файлы на сервере.
На jQuery v2.2.4 ОК. На старой версии будет ошибка:
источник
filename.match(/filename=(.*)/)[1]
(без двойных кавычек или знака вопроса) - regex101.com/r/2AsD4y/2 . Тем не менее, ваше решение было единственным решением, которое сработало после многих поисков.Добавив еще несколько вещей к ответу выше для скачивания файла
Ниже приведен код Java Spring, который генерирует массив байтов.
Теперь в коде JavaScript, используя FileSaver.js, можете скачать файл с кодом ниже
Выше будет скачать файл
источник
Итак, вот рабочий код при использовании MVC, и вы получаете свой файл из контроллера
Допустим, у вас есть объявление и заполнение вашего байтового массива, единственное, что вам нужно сделать, это использовать функцию File (используя System.Web.Mvc)
а затем, в том же контроллере, добавить 2 функции
и тогда вы сможете позвонить своему контроллеру, чтобы загрузить и получить ответный звонок «успех» или «сбой»
источник
Я нашел исправление, которое хотя на самом деле не использует ajax, но позволяет вам использовать вызов javascript для запроса загрузки, а затем получить обратный вызов, когда загрузка фактически начнется. Я нашел это полезным, если ссылка запускает серверный скрипт, который требует немного времени для создания файла перед его отправкой. так что вы можете предупредить их, что он обрабатывает, а затем, когда он, наконец, отправит файл, удалить это уведомление об обработке. вот почему я хотел попробовать загрузить файл через ajax для начала, чтобы у меня могло произойти событие, когда файл запрашивается, и другое, когда он фактически начинает загрузку.
JS на первой странице
фрейм
тогда другой файл:
Я думаю, что есть способ прочитать данные с использованием js, поэтому никакой php не понадобится. но я не знаю это от руки, и сервер, который я использую, поддерживает php, так что это работает для меня. думал, что поделюсь этим на случай, если это кому-нибудь поможет.
источник
Если вы хотите использовать jQuery File Download, обратите внимание на это для IE. Вам нужно сбросить ответ или он не будет загружен
Ваше действие может быть реализовано
ServletResponseAware
для доступаgetServletResponse()
источник
Несомненно, что вы не можете сделать это с помощью вызова Ajax.
Тем не менее, есть обходной путь.
Шаги:
Если вы используете form.submit () для загрузки файла, вы можете сделать следующее:
Это полезно в том случае, если вы хотите решить, нужно ли загружать файл после выполнения form.submit (), например: может быть случай, когда в form.submit () возникает исключение на стороне сервера и вместо этого в случае сбоя может потребоваться показать настраиваемое сообщение на стороне клиента, в этом случае эта реализация может помочь.
источник
есть другое решение для загрузки веб-страницы в ajax. Но я имею в виду страницу, которая должна быть сначала обработана, а затем загружена.
Для начала нужно отделить обработку страницы от загрузки результатов.
1) В вызове ajax выполняются только расчеты страницы.
Я надеюсь, что это решение может быть полезным для многих, как и для меня.
источник
источник
Вот так все отлично работает в любом браузере (я использую ядро asp.net)
источник
Я долго боролся с этой проблемой. Наконец, элегантная внешняя библиотека, предложенная здесь, выручила меня.
источник