Атрибут загрузки тега HTML-привязки не работает в Firefox для jpg и png файлов

В моем веб-приложении я поддерживал пользователя для загрузки любого типа документа (.png,.jpg,.docx,.xls,...)
Я пытаюсь реализовать функции загрузки для этих документов.

В Google Chrome, если вы нажмете на ссылку "Загрузить ссылку", откроется диалоговое окно "Сохранить" для всех вышеперечисленных документов.

В Mozilla Firefox для docx и xls отлично работает, в диалоговом окне "Сохранить" отображается , но для .png и .jpg. не работает должным образом, то есть диалоговое окно загрузки или диалоговое окно "Сохранить" не отображаются, он напрямую открывает это изображение.

Мой код:

<a href="/img/14340.jpg" download="14340.jpg">Download</a>

Я попробовал почти все решения, упомянутые в stackoverflow и предлагаемые Google. Но большинство из них говорит, что "проверьте версию firefox" и другие изменения, такие как: попробуйте добавить элемент в DOM, прежде чем запускать клик

Удалить имя файла из тега загрузки с булевым типом и т.д.

Я также попробовал урок w3schools на теге привязки и атрибуте загрузки, но ничего не работает.

Моя версия Mozilla Firefox: 38.0.5

P.S.: в хроме, а также в firefox.docs,.xls,.pdf документы работают нормально, проблема заключается в .png и .jpg в firefox.

Ответ 1

Firefox будет обрабатывать png и jpeg, используя обработку по умолчанию, которая должна встроить их в документ. При нажатии ссылки, даже если атрибут загрузки определен, кажется, что Firefox считает, что у него есть новое изображение, игнорирующее его аспект загрузки. Это может быть временная ошибка.

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

Он не работает встроенный в Stackoverflow, поэтому вам нужно проверить его на jsFiddle.

Код выполняет следующие действия:

  • Сканирует документ для тегов.
  • Те, у которых есть набор data-link, будут иметь общий клик-обработчик.
  • При нажатии ссылки извлекается из атрибута data-link (href is se to #), загружается как ArrayBuffer через XHR (требования CORS применяются, а не проблема в этом случае) и преобразуется в объект -URL с Blob, установленным в mime-type octet/stream
  • URL-адрес объекта устанавливается как window.location для перенаправления на эти двоичные данные, которые заставят браузер запрашивать у пользователя загрузку файла.
var links = document.querySelectorAll("a"), i = 0, lnk;

while(lnk = links[i++]) {
  if (lnk.dataset.link.length) lnk.onclick = toBlob;
}

function toBlob(e) {
  e.preventDefault();
  var lnk = this, xhr = new XMLHttpRequest();
  xhr.open("GET", lnk.dataset.link);
  xhr.responseType = "blob";
  xhr.overrideMimeType("octet/stream");
  xhr.onload = function() {
    if (xhr.status === 200) {
      window.location = (URL || webkitURL).createObjectURL(xhr.response);
    }
  };
  xhr.send();
}

Пример тега:

<a href="#" data-link="image.jpg">Click to download</a>

Недостатком является то, что вы потеряете расширение в имени файла.

Это также можно сделать с использованием URL-адреса данных, но URL-адрес данных имеет накладные расходы 166% по сравнению с использованием ArrayBuffer и blob.

Ответ 2

У меня была похожая проблема с Firefox, не обрабатывающим атрибут загрузки, даже для файлов с одним доменом.

Мои целевые файлы фактически размещены на AWS, поэтому они являются междоменными. Я справился с этим с помощью конечной точки того же домена, которая загружает удаленный файл и передает его клиенту.

const express = require('express')
const {createWriteStream} = require('fs')
const downloadVideo = (url) => { return new Promise((resolve, reject) => {
  const filePath = '/tmp/neat.mp4'
  const ws = createWriteStream(filePath)
  request(url, {}, (error, response, body) => {
    if(error) { return reject(error) }
    resolve(filePath)
  }).pipe(ws)
})}

app.get('/api/download', async (req, res) => {
  const videoPath = await downloadVideo(req.query.url)
  res.sendFile(videoPath)
})

На клиенте я отправляю путь к файлу в конечную точку загрузки, чтобы получить большой двоичный объект, который затем преобразуется в URL объекта. Оттуда это стандартная загрузка атрибутов.

async download(remoteFilePath){
  const a = document.createElement('a')
  const dlURL = '/api/download?url=${encodeURIComponent(remoteFilePath)}'
  const blob = await fetch(dlURL).then(res => res.blob())
  a.href = URL.createObjectURL(blob)
  a.setAttribute('download', 'cool.mp4')
  document.body.appendChild(a)
  a.click()
  a.remove()
}

Ответ 3

Загрузка HTML5 Атрибут не работает для сайтов с перекрестным происхождением. Чтобы увидеть это введите ссылку здесь

Но мы можем найти другой способ решить этот вопрос. Это использование холста 1. Чтобы унифицировать imageurl до base64 DataURL Тогда изображение является локальным изображением

<a id="download" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAEiElEQVRYR82YXWgcVRTH/2d2N82K2UKrBUEamyhWUojdSXfWmkJSmu6Hpk8a7JOKJkE09akWHwRBUGhetC2CiagPajH6ItXsTBJMICFmNjtTCwmKmNYUQaip0E1pPnZ2jswmG7ub3exsM5rO65x77u+ee/73nnsIZX4B5dIecDoE5kYiPAagGkDVqpt5ALPM+BlEYyCXEg/VXylnCrJj/Gxfn2u26uE2EL9GoFpiyACPpCFMm0b6yuKCN2n5qfQu+AS3a48LZh1ATUwIM3gGTOeq53/r+7qtLV1qvpJAQVk/wuCzDPxNEE4b96X7tYaGVCnH1n8xkfC451xRhvkGATsI1DUR9g9tNLYoUNPwcOXCou8DEI4S4cRESLxgB6KYTVDRWplxBowBb2Xy9ZHm5sVCtgWBDvXr96cE/h5Ev3N6+WU1GsxsyWY/qX/CR66Kj8H8kMekp0aj/r/yfa4DsmCWBR5l4Jt4yP8WiHizIDnjmSmg6O8Q8EyFSYfyoXKAxAuJe9we+gFMw2rE/6ajIHnOpJj+HoibjRQf1lobbmV/5wAFZL0XYF885H/O8cjkr46ZpAH9S2a6GQ/729cBraqpF2aq3qmcKRVhK6cguH8iCB1Z9a1E6G0WpKA+RYRTdtUkxbQZAENqROzMTry6qEECtZSS99qYFfWd3p2c2WedUxmgQEw/TsCrasTfWGpV2f9OAVn+JFkbZaYP4xH/+QyQFNPHQNSthvd/WwhIkrXNK43QqYbEnkL+gzH9mEl8Kh4WnyTrbiJO/+jdduPBkeZmYysi1DQ87F5Y2v6H6U4fpKCSeAWmIE1E/C/YhVmJqjM5tJYCsvYpEccpENM+F4ChiYj4WTlATtsGlMTzMKmFJDlx0WRXx2Rk/2Q5kxRSVKGo2fUZGNAbYHIPSbI2Z6R4r9baMFdssKRoHWB8VOj/7RLPABFq1tkxLqsRsXYjuMCQupMMz68W0NIO0+eLRR9Zsrsay87pCNX1TVfc61uczwDdTFZWTbfVLd8tQHPsNh6NH5Gu/2dbZp3oYbHF5pYlLrIgtMeP+hNbGSErqck0eyko61+AebBc2TudQ2uytw5Gq2ZSw+KLWxkhKXswHhiarBEM1/hGV0dROQOwJfs8u/yF51wddi7Xghfiymskp9S404Mx53K90/LDyRxaV35YD8GrvtopJpyMh8Tv7OSSU0ABRXuaGN05Bdq/J6/ZA9N4/P8uYUHcqYYODFocOUW+JGufgOBVQ+JxO1HarI2kaOfBuKWGxZeyvrbuGaTo74L58IbPIIvyrnooZsN2ULm0K81GPwMzZKbancop69nDgqeXgFoXuaPjofpr+dtetNnwRN+416za9j6IW5johF31FcurFTXxGTANlt1suN2ppEy2gIWzAK4RoTu1k+Vy2jGe6xRmxkkAu0BmV1ZNxcBL9oesgdmGFRF3AVQDcIyJRwg0ZSzzLB7AjcwEf2K7u4KqGbyPmJoARAHMMPhcdfLyV440rPJXknk2makICI0M2kvAbgC+VbskA1cJ/AsYYyx4YuW29P4BGmfO2Alhem8AAAAASUVORK5CYII=" download="image.jpg">downimage</a>

Ответ 4

Поскольку вы используете атрибут HTML5, каждый браузер обрабатывает по-разному. Поэтому используйте https://github.com/dcneiner/Downloadify для принудительной загрузки клиентской стороны вместо просмотра в браузере.