简体   繁体   中英

HTML anchor tag download attribute not working in Firefox for jpg and png files

In my web application I have supported user to upload any type of document (.png, .jpg, .docx, .xls, ... )
I'm trying to implement download functionality for these documents.

In Google Chrome if you click on Download link Save dialog is shown for all above documents.

In Mozilla Firefox for docx and xls works fine, Save dialog is shown but for .png and .jpg download tag is not working as expected ie, download dialog or Save dialog does not appear, it directly open that image.

My code:

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

I have tried almost all solutions mentioned on stackoverflow and suggested by Google. But most of them says that 'check firefox version' and other changes like: try adding the element to the DOM before triggering the click

Remove filename from download tag it is of boolean type and etc.

I have also tried w3schools lesson on anchor tag and download attribute but nothing seems to be working.

My Mozilla Firefox version is: 38.0.5

PS: in chrome as well as in firefox .docs, .xls, .pdf documents work fine, problem is for .png and .jpg in firefox.

Firefox will handle png and jpeg using default handling, which is to inline them in the document. When clicking a link, even if download attribute is defined, seem to make Firefox think it has a new image ignoring the download aspect of it. This may be a temporary bug.

Here is a way, admittedly not super-elegant, to get around this problem forcing the image to be interpreted as an octet-stream.

It does not work inline on Stackoverflow so you have to test it on jsFiddle.

The code does the following:

  • Scans the document for a-tags.
  • Those which has data-link set will have a common click-handler attached.
  • When clicked the link is extracted from the data-link attribute ( href is se to #), loaded as an ArrayBuffer via XHR (CORS requirements applies, not a problem in this case), and is converted to an Object-URL with the Blob set to mime-type octet/stream
  • The Object URL is set as window.location to redirect to this binary data which will make the browser ask user to download the file instead.
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();
}

Example tag:

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

The drawback is that you'll loose the extension in the filename.

This is also possible to do using a Data-URL, but a data-url has a 166% overhead compared to using ArrayBuffer and a blob.

I had a similar problem with firefox not handling the download attribute, even for same-domain files.

My target files are actually hosted on AWS, so they are cross-domain. I got around this with a same-domain endpoint that downloads the remote file and pipes it to the client.

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)
})

On the client, I send the file path to the download endpoint to get a blob back, which is then converted to an object url. From there, it's standard download attribute stuff.

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()
}

As you are using HTML5 attribute, each browser handling differently. So use https://github.com/dcneiner/Downloadify for client side forceful download instead of viewing in browser.

HTML5 Download Attribute doesn't work for cross origin sites. To see this enter link description here

But we can find another way to solve this question. That is use the canvas 1. To convent the imageurl to base64 DataURL Then the image is local image

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM