загрузка файла с помощью JavaScript

Допустим, у меня есть ссылки для скачивания файлов на моем сайте.

При щелчке по этим ссылкам отправляется запрос AJAX на сервер, который возвращает URL с указанием местоположения файла.

Я хочу, чтобы браузер загрузил файл при получении ответа. Есть ли портативный способ сделать это?

13.12.2008 21:37:03
12 ОТВЕТОВ
РЕШЕНИЕ

Попробуйте эту библиотеку https://github.com/PixelsCommander/Download-File-JS. Она более современная, чем все решения, описанные ранее, поскольку использует атрибут «download» и комбинацию методов для получения наилучшего опыта.

Объясняется здесь - http://pixelscommander.com/en/javascript/javascript-file-downliading-ignore-content-type/

Кажется, это идеальный кусок кода для начала загрузки в JavaScript.

4
26.10.2013 22:11:18

Я предлагаю сделать невидимый iframe на странице и установить его src на URL, который вы получили с сервера - загрузка начнется без перезагрузки страницы.

Или вы можете просто установить текущий document.location.href для полученного URL-адреса. Но это может привести к тому, что пользователь увидит ошибку, если запрошенный документ фактически не существует.

2
13.12.2008 22:07:48
когда будет безопасно удалить iframe из DOM?
AMember 3.11.2013 12:19:54

Согласитесь с методами, упомянутыми maxnk, однако вы можете пересмотреть попытку автоматически заставить браузер загрузить URL. Он может хорошо работать для двоичных файлов, но для других типов файлов (текст, PDF, изображения, видео) браузер может захотеть отобразить его в окне (или в IFRAME), а не сохранить на диск.

Если вам действительно нужно сделать Ajax-вызов для получения окончательных ссылок на скачивание, как насчет использования DHTML для динамической записи ссылки на скачивание (из ответа ajax) на страницу? Таким образом, пользователь может либо щелкнуть по нему для загрузки (если он двоичный), либо просмотреть в своем браузере - либо выбрать «Сохранить как» по ссылке, чтобы сохранить на диск. Это дополнительный щелчок, но у пользователя больше контроля.

3
13.12.2008 22:14:33
О да, я забыл о недвоичных, спасибо. В качестве альтернативы может быть хорошим решением создать оболочку для потока файлов с сервера и установить заголовок «Content-Disposition: attachment». Но это подходит только для небольших файлов.
maxnk 13.12.2008 22:53:19
Или вы можете попытаться заставить браузер думать, что загружаемый файл является двоичным, если сервер отправит заголовок «Content-Type» как «application / octet-stream», независимо от того, какой тип файла используется
Marc Novakowski 14.12.2008 01:24:40
Internet Explorer 8 блокирует загрузку файлов всеми упомянутыми способами (iframe, window.location.href или даже «http-equ = REFRESH CONTENT»). «Чтобы защитить вашу безопасность, IE заблокировал этот сайт от загрузки файлов на ваш компьютер ...». Вы знаете способ подавить это предупреждение и начать загрузку, как, скажем, Firefox? Я проверил несколько сайтов: Skype, Google (с Picasa) и Download.com выдают предупреждение при загрузке (потому что они показывают своего рода страницу «спасибо»). Спасибо за ваши мысли!
Mar 20.11.2009 10:55:51
Установите заголовки для этого типа файла в htaccess.
Matt K 14.03.2014 18:22:36

Я бы предложил window.open()открыть всплывающее окно. Если это загрузка, окна не будет, и вы получите свой файл. Если есть 404 или что-то еще, пользователь увидит его в новом окне (следовательно, его работа не будет беспокоить, но он все равно получит сообщение об ошибке).

1
13.12.2008 22:24:29
это работает нормально, если вы имеете дело с пользовательской ссылкой (но почему она вообще была js?), она все равно столкнется с нарушением безопасности IE.
Laith 28.03.2011 20:18:55

Если это ваше собственное серверное приложение, то я предлагаю использовать следующий заголовок

Content-disposition: attachment; filename=fname.ext

Это заставит любой браузер загрузить файл, а не отображать его в окне браузера.

10
13.12.2008 23:10:54

Просто позвоните window.location.href = new_urlиз своего javascript, и он перенаправит браузер на этот URL-адрес, как это было введено пользователем в адресную строку.

11
13.12.2008 23:20:13

Мы делаем это так: сначала добавьте этот скрипт.

<script type="text/javascript">
function populateIframe(id,path) 
{
    var ifrm = document.getElementById(id);
    ifrm.src = "download.php?path="+path;
}
</script>

Поместите это туда, где вы хотите кнопку загрузки (здесь мы используем только ссылку):

<iframe id="frame1" style="display:none"></iframe>
<a href="javascript:populateIframe('frame1','<?php echo $path; ?>')">download</a>

Файл 'download.php' (должен быть размещен на вашем сервере) просто содержит:

<?php 
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=".$_GET['path']);
   readfile($_GET['path']);
?>

Поэтому, когда вы нажимаете на ссылку, скрытый iframe получает / открывает исходный файл «download.php». С путем в качестве параметра получения. Мы считаем, что это лучшее решение!

Следует отметить, что PHP-часть этого решения является простой демонстрацией и потенциально очень и очень небезопасной. Это позволяет пользователю загружать любой файл, а не только заранее заданный набор. Это означает, что они могут загружать части исходного кода самого сайта, возможно, содержащие учетные данные API и т. Д.

25
21.09.2015 20:19:24
@ Фабио: if (!file_exists($path)) { header("HTTP/1.1 404 Not Found"); exit; }должен сделать трюк
S B 25.08.2011 14:28:42
Есть ли способ для javascript узнать ход загрузки (или просто ли он завершен)?
lakenen 24.01.2012 15:31:12
Что мешает пользователю просмотреть источник, получить URL для download.php, а затем перейти на yoursite.com/download.php?path=config.php, чтобы попытаться получить ваши пароли? Говоря иначе: Пожалуйста, пожалуйста , не делайте это так.
Grim... 13.08.2012 15:00:41
После комментария @Grim ... он определенно прав, НЕ делайте так. Сделайте ссылку iframe src непосредственно на файл и используйте .htaccess для установки информации заголовка для этого конкретного типа файла.
Matt K 14.03.2014 18:20:24
Некоторые безопасные альтернативы: 1) Проверьте запрошенный путь по сравнению с белым списком, 2) Создайте карту id => filepath и используйте вместо нее идентификатор.
Svish 29.09.2014 07:38:27

Я создал плагин jQuery File Download с открытым исходным кодом ( демонстрация с примерами ) ( GitHub ), который также может помочь в вашей ситуации. Он работает примерно так же с iframe, но имеет несколько интересных функций, которые я нашел довольно полезными:

  • Пользователь никогда не покидает ту же страницу, с которой он инициировал загрузку файла. Эта функция становится критически важной для современных веб-приложений
  • Протестированная поддержка кросс-браузеров (в том числе и мобильных)
  • Он поддерживает запросы POST и GET аналогично AJAX API jQuery.
  • Функции successCallback и failCallback позволяют вам четко указывать, что видит пользователь в любой ситуации
  • В сочетании с пользовательским интерфейсом jQuery разработчик может легко показать модал, сообщающий пользователю, что происходит загрузка файла, расформировать модал после начала загрузки или даже дружески проинформировать пользователя о том, что произошла ошибка. Посмотрите Демо для примера этого.
18
21.06.2012 21:53:05
Привет. Есть ли способ запретить Internet Explorer 8 блокировать загрузку? Информационная панель Internet Explorer запрашивает подтверждение загрузки, в результате чего страница перезагружается и не загружается, в результате чего пользователь должен снова щелкнуть ссылку загрузки. Заранее спасибо
Pierpaolo 27.05.2013 11:19:37
Это как раз то, что мне было нужно. Спасибо!
Tobia 4.12.2013 18:46:14

Читая ответы, в том числе принятые, я хотел бы указать на последствия для безопасности, связанные с передачей пути непосредственно в readfile через GET.

Некоторым это может показаться очевидным, но некоторые могут просто скопировать / вставить этот код:

<?php 
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=".$_GET['path']);
   readfile($_GET['path']);
?>

Так что же произойдет, если я передам что-то вроде '/ path / to / fileWithSecrets' этому сценарию? Данный скрипт с удовольствием отправит любой файл, к которому у пользователя веб-сервера есть доступ.

Пожалуйста, обратитесь к этому обсуждению для получения информации о том, как предотвратить это: Как мне убедиться, что путь к файлу находится в данном подкаталоге?

14
23.05.2017 11:46:48
Ссылка непосредственно на файл в iframe и установка заголовков в htaccess.
Matt K 14.03.2014 18:22:06

Почему вы делаете вещи на стороне сервера, когда все, что вам нужно, это перенаправить браузер в другой файл window.location.href?

Вот код, который анализирует? File = QueryString ( взятый из этого вопроса ) и перенаправляет пользователя на этот адрес за 1 секунду (у меня работает даже в браузерах Android):

<script type="text/javascript">
    var urlParams;
    (window.onpopstate = function () {
        var match,
        pl = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
        query = window.location.search.substring(1);

        urlParams = {};
        while (match = search.exec(query))
            urlParams[decode(match[1])] = decode(match[2]);
    })();

    (window.onload = function() {
        var path = urlParams["file"];
        setTimeout(function() { document.location.href = path; }, 1000);
    });
</script>

Если в вашем проекте есть jQuery, обязательно удалите эти обработчики window.onpopstate & window.onload и сделайте все в $ (document) .ready (function () {});

1
23.05.2017 11:54:12

Чтобы обойти уязвимость в ответе с наибольшим количеством голосов, вы можете установить iframe src непосредственно в нужный файл (вместо промежуточного php-файла) и установить информацию заголовка в файле .htaccess:

<Files *.apk>
     ForceType application/force-download
     Header set Content-Disposition attachment
     Header set Content-Type application/vnd.android.package-archive
     Header set Content-Transfer-Encoding binary
</Files>
3
14.03.2014 18:26:37

Относительно верхнего ответа у меня есть возможное решение проблемы безопасности.

<?php
     if(isset($_GET['path'])){
         if(in_array($_GET['path'], glob("*/*.*"))){
             header("Content-Type: application/octet-stream");
             header("Content-Disposition: attachment; filename=".$_GET['path']);
             readfile($_GET['path']);
         }
     }
?>

Используя функцию glob () (я проверил загружаемый файл по пути, находящемуся в одной папке от загружаемого файла), я смог создать быстрый массив файлов, которые «разрешены» для загрузки, и проверил пройденный путь по нему. , Это не только гарантирует, что извлекаемый файл не является чем-то чувствительным, но также проверяет наличие файлов одновременно.

~ Примечание: Javascript / HTML ~

HTML:

<iframe id="download" style="display:none"></iframe>

а также

<input type="submit" value="Download" onclick="ChangeSource('document_path');return false;">

JavaScript:

<script type="text/javascript">
    <!--
        function ChangeSource(path){
            document.getElementByID('download').src = 'path_to_php?path=' + document_path;
        }
    -->
</script>
2
17.09.2015 18:14:52
Правильно, но это строилось на верхнем ответе. Я добавлю аналогичное соединение JavaScript, хотя.
James Bordine II 17.09.2015 18:02:08