загрузка файла с помощью JavaScript - PullRequest
53 голосов
/ 14 декабря 2008

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

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

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

Ответы [ 12 ]

24 голосов
/ 10 января 2011

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

<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 и т. Д.

18 голосов
/ 16 июня 2012

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

  • Пользователь никогда не покидает ту же страницу, с которой он инициировал загрузку файла. Эта функция становится критически важной для современных веб-приложений
  • Протестированная поддержка кросс-браузеров (включая мобильные!)
  • Он поддерживает запросы POST и GET аналогично AJAX API jQuery
  • Функции successCallback и failCallback позволяют вам четко указывать, что пользователь видит в любой ситуации
  • В сочетании с пользовательским интерфейсом jQuery разработчик может легко показать модальное сообщение, сообщающее пользователю, что происходит загрузка файла, распустить модальное устройство после начала загрузки или даже дружески проинформировать пользователя о том, что произошла ошибка. Посмотрите Демо для примера этого.
14 голосов
/ 02 декабря 2012

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

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

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

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

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

10 голосов
/ 14 декабря 2008

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

Content-disposition: attachment; filename=fname.ext

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

7 голосов
/ 14 декабря 2008

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

3 голосов
/ 14 марта 2014

Чтобы обойти уязвимость в ответе с наибольшим количеством голосов, вы можете установить 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 голосов
/ 06 апреля 2013

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

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

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

3 голосов
/ 14 декабря 2008

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

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

2 голосов
/ 20 августа 2015

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

<?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 голосов
/ 14 декабря 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...