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

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

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

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
60
0
131 873
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

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

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

когда будет безопасно удалить iframe из DOM?

AMember 03.11.2013 16:19

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

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

Ах да, я забыл о небинарных файлах, спасибо. В качестве альтернативы может быть хорошим решением создать оболочку вокруг файлового потока с сервера и установить заголовок «Content-Disposition: attachment». Но подходит только для небольших файлов.

maxnk 14.12.2008 01:53

Или вы можете попытаться обмануть браузер, заставив его думать, что загружаемый файл является двоичным, попросив сервер отправить заголовок Content-Type как «application / octet-stream», независимо от фактического типа файла.

Marc Novakowski 14.12.2008 04:24

Internet Explorer 8 блокирует загрузку файлов всеми упомянутыми способами (iframe, window.location.href или даже «http-Equiv = REFRESH CONTENT»). «Чтобы защитить вашу безопасность, IE заблокировал загрузку файлов с этого сайта на ваш компьютер ...». Вы знаете способ подавить это предупреждение и начать загрузку, как, скажем, Firefox? Я проверил несколько сайтов: Skype, Google (с Picasa) и Download.com вызывает предупреждение при загрузке (потому что они показывают своего рода страницу с благодарностью). Спасибо за ваши мысли!

Mar 20.11.2009 13:55

Установите заголовки для этого типа файла в htaccess.

Matt K 14.03.2014 22:22

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

это отлично работает, если вы имеете дело с ссылкой, нажатой пользователем (но тогда почему она вообще должна быть js?), она все равно столкнется с нарушением безопасности IE.

Laith 29.03.2011 00:18

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

Content-disposition: attachment; filename=fname.ext

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

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

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

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

@Fabio: if (!file_exists($path)) { header("HTTP/1.1 404 Not Found"); exit; } должен помочь

S B 25.08.2011 18:28

Есть ли способ для javascript узнать о ходе загрузки (или просто о том, завершен ли он)?

lakenen 24.01.2012 19:31

@camupod Я так не думаю. Если вам нужен прогресс загрузки, вам нужно использовать XmlHttpRequest Level 2. w3.org/TR/XMLHttpRequest/#event-xhr-progress

devios1 31.07.2012 21:37

Что мешает пользователю просмотреть исходный код, получить URL-адрес для download.php, а затем перейти к yoursite.com/download.php?path=config.php, чтобы попытаться получить ваши пароли? Другими словами: пожалуйста, пожалуйста, не делай этого так.

Grim... 13.08.2012 19:00

@Grim ... Мне просто пришло в голову возможное решение, вы могли бы использовать относительный путь из вашего файла download.php, что-то вроде readfile ("../ public /".$_ GET ['path']); а затем все, что вам нужно сделать перед этим, это проверить, что $ _GET ['path'] нигде не содержит "..". Может это сработать? По общему признанию, это немного взлом, но быстрое небольшое решение?

Nick M 05.12.2013 09:07

Относительный путь может быть чем-то вроде /common/config.php. Думаю, вы могли бы убедиться, что первым символом не является '/', но держу пари, что есть еще много способов добраться туда.

Grim... 11.12.2013 15:11

Большое спасибо - без присланных заголовков я не мог заставить его работать ни в IE, ни в Chrome. Так что это решение отлично работает!

jazkat 30.01.2014 18:21

Следуя комментарию @Grim ..., он определенно прав, НЕ делайте этого таким образом. Сделайте ссылку iframe src непосредственно на файл и используйте .htaccess, чтобы установить информацию заголовка для этого конкретного типа файла.

Matt K 14.03.2014 22:20

@ Мрачный ... Какая безопасная альтернатива? Почему вы не отвечаете или не редактируете ответ ..?

hitautodestruct 18.03.2014 13:53

Некоторые безопасные альтернативы: 1) Проверьте запрошенный путь по белому списку, 2) Создайте карту id => filepath и используйте вместо этого id.

Svish 29.09.2014 11:38

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

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

Привет. Есть ли способ запретить Internet Explorer 8 блокировать загрузку? Информационная панель Internet Explorer запрашивает подтверждение загрузки, что приводит к перезагрузке страницы без загрузки, в результате чего пользователь должен еще раз щелкнуть ссылку для загрузки. заранее спасибо

Pierpaolo 27.05.2013 15:19

Это как раз то, что мне нужно. Спасибо!

Tobia 04.12.2013 22:46

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

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

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

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

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

Свяжите напрямую с файлом в iframe и установите заголовки в htaccess.

Matt K 14.03.2014 22:22

Это должен быть комментарий, а не ответ.

cemper93 06.07.2020 22:05

Зачем вы делаете вещи на стороне сервера, когда все, что вам нужно, это перенаправить браузер на другой 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 () {});

Ответ принят как подходящий

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

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

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

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

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

<?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>

Верно, но это основывалось на верхнем ответе. Тем не менее, я добавлю аналогичное соединение JavaScript.

James Bordine II 17.09.2015 21:02

Другие вопросы по теме