Лучший способ загрузки файлов в JavaScript
Скачивание файла – что может быть проще? Однако как и везде – в этом вопросе есть подводные камни и нет предела совершенству. В статье описывается лучший способ скачать файл в JavaScript.
Если вам не нужна теория о загрузке файлов в JavaScript и вы просто хотите подключить функцию downloadFile к проекту – вам на GitHub.
Как правило в HTML среде используются два пути вызова загрузки: window.open и клик по ссылке на файл. Каждый из способов по своему ущербный. В поиске универсальной техники было найдено несколько интересных решений, все вместе они составляют лучший метод для скачивания файлов из JS.
Начнем с простого метода загрузки файла через window.open:
window.downloadFile = function(sUrl) {
window.open(sUrl);
}
Эта функция будет работать везде, но с рядом недостатков:
- В Chrome и Safari после срабатывания останется пустое окно;
- Если content-type файла предполагает открытие то файл не скачается, а отобразится в открывшемся окне.
Что же мы можем предпринять?
Аргумент “_self” для window.open
Убрать назойливое окно в Chrome и Safari можно добавив аргумент “_self” к window.open:
window.downloadFile = function(sUrl) {
window.open(sUrl, '_self');
}
Виртуальный клик
Клик по ссылке так же не вызывает упомянутой выше проблемы с пустым окном и хоть клик – операция пользователя, нам никто не мешает создать виртуальную ссылку и виртуально по ней кликнуть сгенерировав событие мыши.
Добавим код виртуального щелчка для хрома и сафари, оставляя за кадром банальное определение браузера:
if (window.downloadFile.isChrome || window.downloadFile.isSafari) {
//Creating new link node.
var link = document.createElement('a');
link.href = sUrl;
//Dispatching click event.
if (document.createEvent) {
var e = document.createEvent('MouseEvents');
e.initEvent('click' ,true ,true);
link.dispatchEvent(e);
return true;
}
}
HTML5 аттрибут download и игнорирование content-type Что еще может вызвать раздражение пользователя? Например ситуация, когда при загрузке HTML или PNG файла он открывается в браузере. Этого можно избежать добавивши к нашему виртуальному линку аттрибут download, который появился в HTML5 и служит для указания браузеру на “скачивающий” характер ссылки. Значение аттрибута – это итоговое имя скачиваемого файла, а href – исходный URL. Итоговый код модуля download.js:
window.downloadFile = function(sUrl) {
//If in Chrome or Safari - download via virtual link click
if (window.downloadFile.isChrome || window.downloadFile.isSafari) {
//Creating new link node.
var link = document.createElement('a');
link.href = sUrl;
if (link.download !== undefined){
//Set HTML5 download attribute. This will prevent file from opening if supported.
var fileName = sUrl.substring(sUrl.lastIndexOf('/') + 1, sUrl.length);
link.download = fileName;
}
//Dispatching click event.
if (document.createEvent) {
var e = document.createEvent('MouseEvents');
e.initEvent('click' ,true ,true);
link.dispatchEvent(e);
return true;
}
}
// Force file download (whether supported by server).
var query = '?download';
window.open(sUrl + query, '_self');
}
window.downloadFile.isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
window.downloadFile.isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1;