Лучший способ загрузки файлов в 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;