Самый простой способ открыть окно загрузки, не уходя со страницы

119

Каков наилучший кроссбраузерный способ открыть диалоговое окно загрузки (предположим, мы можем установить content-dision: attachment в заголовках) без перехода с текущей страницы или открытия всплывающих окон, что плохо работает в Internet Explorer (IE ) 6.

mkoryak
источник

Ответы:

107

Прошло 7 лет, и я не знаю, работает ли он для IE6 или нет, но это вызывает OpenFileDialog в FF и Chrome.

var file_path = 'host/path/file.ext';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
0x000f
источник
Сначала спасибо за это решение, но я обнаружил ошибку, если removeChild (a) zip будет распаковывать ошибку, если zip сломан, поэтому удалите этот код, решите это
Рой
2
@Manoj Rana - Я проверил на FF 58.0.2 (64-бит), он работает. Он не будет работать ни с одним FF, если вы удалите 2 строки document.body.appendChild (a); document.body.removeChild (а);
0x000f 09
1
Чтобы он работал на Edge 16, заголовок, откуда приходит файл, должен содержать Content-Type: application/octet-streamи Content-Disposition: attachment.
Саймон
12
это больше не работает developers.google.com/web/updates/2018/02/…
Paulius Dragunas
2
@ user1933131 хром удаляет только для кросс-происхождения
Brandy23
202

Этот javascript хорош тем, что не открывает новое окно или вкладку.

window.location.assign(url);
мозгра
источник
18
Это то же самое, что и window.location = url; «Каждый раз, когда объекту местоположения присваивается новое значение, документ загружается с использованием URL-адреса, как если бы window.location.assign () был вызван с измененным URL-адресом» - developer.mozilla.org/en-US/docs/ Web / API / window.location
Роб Юурлинк,
13
Это приводит к отключению соединения WebSocket.
igorpavlov
4
Я использовал то же решение, но он открывает файл на той же вкладке вместо открытия диалогового окна загрузки.
Techno Cracker
2
это то же самое, что и window.open (url, '_self'), если URL-адрес предназначен для страницы загрузки.
Эксперт хочет быть
5
При использовании IE11 я обнаружил, что это привело к остановке JS. Итак, для IE 11 я использовал window.open (url, '_blank'), который действительно открывал другую вкладку, однако эта вкладка закрывалась, когда выяснялось, что файл был загружен. Это поддерживало работу JS.
Люк
23

Я всегда добавляю target = "_ blank" к ссылке для скачивания. Это откроет новое окно, но как только пользователь нажмет «Сохранить», новое окно закроется.

Jao
источник
2
Это лучший ответ. В Internet Explorer добавление 'target = "_ blank"' к ссылке, которая должна быть загружена, остановит переход браузера (где печатается «HTML1300: Navigation separated») и, таким образом, может оставить страницу в несогласованном состоянии.
user64141
23

Поместите это в раздел заголовка HTML, установив urlпеременную на URL-адрес загружаемого файла:

<script type="text/javascript">  
function startDownload()  
{  
     var url='http://server/folder/file.ext';    
     window.open(url, 'Download');  
}  
</script>

Затем поместите это в тело, которое автоматически начнет загрузку через 5 секунд:

<script type="text/javascript">  
setTimeout('startDownload()', 5000); //starts download after 5 seconds  
</script> 

( Отсюда .)

Джордж Клагхорн
источник
2
это не работает, потому что в IE6, если пользователь нажимает «сохранить», файл сохраняется, но всплывающее окно остается открытым. Это неприемлемо.
mkoryak
этот код не работает в сафари, не могли бы вы помочь мне решить в сафари, пожалуйста.
Рениш Хант
17

Я знаю, что вопрос был задан, 7 years and 9 months agoно многие опубликованные решения, похоже, не работают, например, использование <iframe>работает только с FireFoxи не работает с Chrome.

Лучшее решение:

Лучшее рабочее решение для открытия всплывающего окна загрузки файла JavaScript- использовать HTMLэлемент ссылки, без необходимости добавлять элемент ссылки к,document.body как указано в других ответах.

Вы можете использовать следующую функцию:

function downloadFile(filePath){
    var link=document.createElement('a');
    link.href = filePath;
    link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
    link.click();
}

В моем приложении я использую это так:

downloadFile('report/xls/myCustomReport.xlsx');

Рабочая демонстрация:

Примечание:

  • Вы должны использовать link.downloadатрибут, чтобы браузер не открывал файл в новой вкладке и не запускал всплывающее окно загрузки.
  • Это было протестировано с несколькими типами файлов (docx, xlsx, png, pdf, ...).
cнŝdk
источник
Как лучше всего отображать загружаемый gif, пока файл не загрузится?
Ctrl_Alt_Defeat
1
@Ctrl_Alt_Defeat Что ж, в этом случае будет непросто отследить процесс загрузки, но одна уловка может заключаться в том, чтобы показать эту анимацию gif при linkщелчке и скрыть ее после тайм-аута, используя этот код:, link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); }вы можете увидеть, как она работает в этом fiddle , но имейте в виду, что это не рекомендуемый способ, с ним лучше справились бы, если бы мы использовали Ajax.
cнŝdk
1
это не работает в firefox. как скачать в firefox?
Манодж Рана
@ManojRana Для светлячок, вы можете использовать iframeувидеть этот ответ .
cнŝdk 08
2
У меня это решение работает в Chrome, Safari и Firefox :)
ariebear
15

Я искал хороший способ использовать javascript для инициации загрузки файла, как и предполагает этот вопрос. Однако эти ответы не помогли. Затем я провел небольшое тестирование xbrowser и обнаружил, что iframe лучше всего работает во всех современных браузерах IE> 8.

downloadUrl = "http://example.com/download/file.zip";
var downloadFrame = document.createElement("iframe"); 
downloadFrame.setAttribute('src',downloadUrl);
downloadFrame.setAttribute('class',"screenReaderText"); 
document.body.appendChild(downloadFrame); 

class="screenReaderText" это мой класс для стилизации содержимого, которое присутствует, но не доступно для просмотра.

css:

.screenReaderText { 
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; 
  margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px; 
}

то же, что .visuallyHidden в html5boilerplate

Я предпочитаю это методу javascript window.open, потому что если ссылка не работает, метод iframe просто ничего не делает, а не перенаправляет на пустую страницу, говоря, что файл не может быть открыт.

window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
window.focus();
alockwood05
источник
6

Использование API файла объектно-URL HTML5 Blob :

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName,fileContents) {
    if(typeof(Blob)!='undefined') { // using Blob
        var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else {
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
}//saveBlobAsFile

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
 */
var saveBlobAsFile = function(fileName, fileContents) {
  if (typeof(Blob) != 'undefined') { // using Blob
    var textFileAsBlob = new Blob([fileContents], {
      type: 'text/plain'
    });
    var downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    if (window.webkitURL != null) {
      downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    } else {
      downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
      downloadLink.onclick = document.body.removeChild(event.target);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
    }
    downloadLink.click();
  } else {
    var pp = document.createElement('a');
    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
    pp.setAttribute('download', fileName);
    pp.onclick = document.body.removeChild(event.target);
    pp.click();
  }
} //saveBlobAsFile

var jsonObject = {
  "name": "John",
  "age": 31,
  "city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";

saveBlobAsFile(fileName, fileContents)

loretoparisi
источник
2
Я считаю, что это лучший способ сделать это !!
Кушал МК
1
Также рекомендуется звонить URL.revokeObjectURL(url), когда файл больше не нужен для освобождения памяти
SleepWalker
5

Изменение местоположения окна может вызвать некоторые проблемы, особенно если у вас есть постоянное соединение, такое как веб-сокет. Поэтому я всегда прибегаю к старому доброму решению iframe.

HTML

<input type="button" onclick="downloadButtonClicked()" value="Download"/>
...
...
...
<iframe style="display:none;" name="hiddenIframe" id="hiddenIframe"></iframe>

Javascript

function downloadButtonClicked() {
    // Simulate a link click
    var url = 'your_download_url_here';
    var elem = document.createElement('a');
    elem.href = url;
    elem.target = 'hiddenIframe';
    elem.click();
}
Bnrdo
источник
5

Если ссылка ведет на действительный URL-адрес файла, просто назначьте window.location.href.

Однако иногда ссылка недействительна, и требуется iFrame.

Сделайте свой обычный event.preventDefault, чтобы предотвратить открытие окна, и если вы используете jQuery, это будет работать:

$('<iframe>').attr('src', downloadThing.attr('href')).appendTo('body').on("load", function() {
   $(this).remove();
});
TaylorMac
источник
2

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

Работа в Chrome, Safari и Firefox

function ajaxDownload(url, filename = 'file', method = 'get', data = {}, callbackSuccess = () => {}, callbackFail = () => {}) {
    $.ajax({
        url: url,
        method: 'GET',
        xhrFields: {
            responseType: 'blob'
        },
        success: function (data) {
            // create link element
            let a = document.createElement('a'), 
                url = window.URL.createObjectURL(data);

            // initialize 
            a.href = url;
            a.download = filename;

            // append element to the body, 
            // a must, due to Firefox
            document.body.appendChild(a);

            // trigger download
            a.click();

            // delay a bit deletion of the element
            setTimeout(function(){
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            }, 100);

            // invoke callback if any 
            callbackSuccess(data);
        },
        error: function (err) {
            // invoke fail callback if any
            callbackFail(err)
        }
    });
М.Б.
источник
0

Как насчет:

<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">

Этот способ работает во всех браузерах (я думаю) и позволяет вам разместить сообщение вроде: «Если загрузка не начнется через пять секунд, нажмите здесь».

Если вам нужно, чтобы это было с javascript ... ну ...

document.write('<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">');

С уважением


источник
0

Для этой цели подойдет небольшой / скрытый iframe.

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

Саймон
источник