Forcer le navigateur à télécharger les fichiers image en un clic


100

J'ai besoin du navigateur pour télécharger les fichiers image comme il le fait en cliquant sur une feuille Excel.

Existe-t-il un moyen de le faire en utilisant uniquement la programmation côté client?

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <script type="text/javascript" src="Scripts/jquery-1.10.2.js">
        $(document).ready(function () {
            $("*").click(function () {
                $("p").hide();
            });
        });
        </script>
    </head>

    <script type="text/javascript">
        document.onclick = function (e) {
            e = e || window.event;
            var element = e.target || e.srcElement;
            if (element.innerHTML == "Image") {
                //someFunction(element.href);
                var name = element.nameProp;
                var address = element.href;
                saveImageAs1(element.nameProp, element.href);
                return false; // Prevent default action and stop event propagation
            }
            else
                return true;
        };

        function saveImageAs1(name, adress) {
            if (confirm('you wanna save this image?')) {
                window.win = open(adress);
                //response.redirect("~/testpage.html");
                setTimeout('win.document.execCommand("SaveAs")', 100);
                setTimeout('win.close()', 500);
            }
        }
    </script>

    <body>
        <form id="form1" runat="server">
            <div>
                <p>
                    <a href="http://localhost:55298/SaveImage/demo/Sample2.xlsx" target="_blank">Excel</a><br />
                    <a href="http://localhost:55298/SaveImage/demo/abc.jpg" id="abc">Image</a>
                </p>
            </div>
        </form>
    </body>
</html>

Comment cela devrait-il fonctionner en cas de téléchargement d'une feuille Excel (que font les navigateurs)?


7
L' downloadattribut.
Šime Vidas

6
La meilleure façon d'assurer le téléchargement d'un fichier est de définir la disposition du contenu côté serveur, la plupart des solutions côté client ne sont pas aussi fiables.
adeneo


Il y a une question similaire à laquelle vous avez déjà répondu: stackoverflow.com/a/6799284/1948211
dschu

Karl-Andre Gagnon: Veuillez le parcourir correctement. [Je n'avais pas tagué HTML 5 car je ne veux pas l'utiliser] et sans serveur de contact
Amit

Réponses:


172

En utilisant HTML5, vous pouvez ajouter l'attribut «télécharger» à vos liens.

<a href="https://stackoverflow.com/path/to/image.png" download>

Les navigateurs conformes inviteront alors à télécharger l'image avec le même nom de fichier (dans cet exemple image.png).

Si vous spécifiez une valeur pour cet attribut, cela deviendra le nouveau nom de fichier:

<a href="https://stackoverflow.com/path/to/image.png" download="AwesomeImage.png">

MISE À JOUR: Au printemps 2018 , ce ne sera plus possible pour le contre-origine hrefs . Donc, si vous souhaitez créer <a href="https://i.imgur.com/IskAzqA.jpg" download>sur un domaine autre que imgur.com, cela ne fonctionnera pas comme prévu. Annonce d'abandons et de suppressions de Chrome


Richard Parnaby-King: En utilisant l'attribut HTML 5, cela peut être fait, mais je dois le faire SANS utiliser HTML5 ou des outils SERVER SIDE (si c'est possible) Merci pour les aides :)
Amit

2
Pas encore entièrement pris en charge dans tous les navigateurs, mais c'est une bonne solution si vous ne vous souciez pas d'IE ou de Safari. caniuse.com/#feat=download
stacigh

Merci pour une solution HTML5. Comment toujours autoriser «enregistrer sous» qui me permet d'entrer un nom de fichier avant de l'enregistrer?
teleman

Ne puis-je pas contrôler où ce fichier doit être téléchargé? Il télécharge simplement pour télécharger le dossier directement. Je veux qu'il utilise le chemin local du fichier html.
Arjun Chiddarwar

1
@ArjunChiddarwar Non, cela ouvre des failles de sécurité (imaginez que quelqu'un enregistre un fichier malveillant directement dans votre dossier Windows). Le chemin de téléchargement est basé sur les paramètres du navigateur - par exemple, Chrome téléchargera par défaut dans votre dossier de téléchargement.
Richard Parnaby-King

96

J'ai réussi à faire fonctionner cela dans Chrome et Firefox également en ajoutant un lien vers le document.

var link = document.createElement('a');
link.href = 'images.jpg';
link.download = 'Download.jpg';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

2
C'est en fait une très bonne solution pour les applications Web où Javascript est partout. Fonctionne uniquement dans Google Chrome (dans ma configuration de test), cependant.
Pavel

Des idées sur un moyen de tester la compatibilité? J'aimerais utiliser cette technique, mais je dois également prendre en charge d'autres navigateurs, je devrais donc proposer une alternative (comme ouvrir un PDF dans une nouvelle fenêtre ou un lien à télécharger) lorsque cela n'est pas pris en charge. Quelqu'un at-il eu de la chance avec ça?
alexrussell

13
Excellente solution, merci! Notez que si vous l'omettez, document.body.appendChild(link)cela ne fonctionnera pas dans Firefox. Il est également bon de supprimer l'élément créé avec document.body.removeChild(link);afterlink.click()
akn

8
meilleure solution. Pour éviter les déchets dans l'utilisation du DOMsetTimeout( function () { link.parentNode.removeChild( link ); },10 );
Mephiztopheles

1
Merci aurait dû être la réponse choisie puisque la question demandait comment le faire dans JAVASCRIPT.
codehelp4

33

Leeroy et Richard Parnaby-King:

MISE À JOUR: À partir du printemps 2018, cela n'est plus possible pour les hrefs d'origine croisée. Donc, si vous souhaitez créer sur un domaine autre que imgur.com, cela ne fonctionnera pas comme prévu. Annonce d'abandons et de suppressions de Chrome

function forceDownload(url, fileName){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.responseType = "blob";
    xhr.onload = function(){
        var urlCreator = window.URL || window.webkitURL;
        var imageUrl = urlCreator.createObjectURL(this.response);
        var tag = document.createElement('a');
        tag.href = imageUrl;
        tag.download = fileName;
        document.body.appendChild(tag);
        tag.click();
        document.body.removeChild(tag);
    }
    xhr.send();
}

2
Les téléchargements d'image mais ne s'ouvre pas car il est indiqué `` L'image est cassée ''
picacode

19

Mise à jour printemps 2018

<a href="/path/to/image.jpg" download="FileName.jpg">

Bien que cela soit toujours pris en charge, à partir de février 2018, Chrome a désactivé cette fonctionnalité pour le téléchargement d'origine croisée, ce qui signifie que cela ne fonctionnera que si le fichier se trouve sur le même nom de domaine.

J'ai trouvé une solution de contournement pour télécharger des images interdomaines après la nouvelle mise à jour de Chrome qui a désactivé le téléchargement interdomaine. Vous pouvez le modifier en une fonction adaptée à vos besoins. Vous pourrez peut-être obtenir l'image de type mime (jpeg, png, gif, etc.) avec quelques recherches supplémentaires si vous en avez besoin. Il existe peut-être un moyen de faire quelque chose de similaire avec les vidéos. J'espère que cela aide quelqu'un!

Leeroy et Richard Parnaby-King:

MISE À JOUR: À partir du printemps 2018, cela n'est plus possible pour les hrefs d'origine croisée. Donc, si vous souhaitez créer sur un domaine autre que imgur.com, cela ne fonctionnera pas comme prévu. Annonce d'abandons et de suppressions de Chrome

var image = new Image();
image.crossOrigin = "anonymous";
image.src = "https://is3-ssl.mzstatic.com/image/thumb/Music62/v4/4b/f6/a2/4bf6a267-5a59-be4f-6947-d803849c6a7d/source/200x200bb.jpg";
// get file name - you might need to modify this if your image url doesn't contain a file extension otherwise you can set the file name manually
var fileName = image.src.split(/(\\|\/)/g).pop();
image.onload = function () {
    var canvas = document.createElement('canvas');
    canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
    canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
    canvas.getContext('2d').drawImage(this, 0, 0);
    var blob;
    // ... get as Data URI
    if (image.src.indexOf(".jpg") > -1) {
    blob = canvas.toDataURL("image/jpeg");
    } else if (image.src.indexOf(".png") > -1) {
    blob = canvas.toDataURL("image/png");
    } else if (image.src.indexOf(".gif") > -1) {
    blob = canvas.toDataURL("image/gif");
    } else {
    blob = canvas.toDataURL("image/png");
    }
    $("body").html("<b>Click image to download.</b><br><a download='" + fileName + "' href='" + blob + "'><img src='" + blob + "'/></a>");
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


Il semble que ce code décode l'image dans une mémoire tampon de pixels dans la mémoire du navigateur, puis la réencode en jpeg / png / gif puis l'encapsule dans un data-uri qui est ensuite stocké localement. Si tel est le cas, cela signifie que toutes les métadonnées du fichier image sont perdues. Le réencodage JPEG perdra également de la qualité et aura un rapport qualité / nombre d'octets plus mauvais. Pourtant, bon à savoir. Merci d'avoir partagé.
Stéphane Gourichon le

14

Une approche plus moderne utilisant Promise et async / await:

toDataURL(url) {
    return fetch(url).then((response) => {
            return response.blob();
        }).then(blob => {
            return URL.createObjectURL(blob);
        });
}

puis

async download() {
        const a = document.createElement("a");
        a.href = await toDataURL("https://cdn1.iconfinder.com/data/icons/ninja-things-1/1772/ninja-simple-512.png");
        a.download = "myImage.png";
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
}

Trouvez la documentation ici: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch


13
var pom = document.createElement('a');
pom.setAttribute('href', 'data:application/octet-stream,' + encodeURIComponent(text));
pom.setAttribute('download', filename);
pom.style.display = 'none';
document.body.appendChild(pom);
pom.click();
document.body.removeChild(pom);     

5
le navigateur safari ne prend pas en charge l'attribut de téléchargement
Pranav Labhe

11

Ceci est une solution générale à votre problème. Mais il y a une partie très importante que l'extension de fichier doit correspondre à votre encodage. Et bien sûr, ce paramètre de contenu de la fonction downlowadImage doit être une chaîne encodée en base64 de votre image.

const clearUrl = url => url.replace(/^data:image\/\w+;base64,/, '');

const downloadImage = (name, content, type) => {
  var link = document.createElement('a');
  link.style = 'position: fixed; left -10000px;';
  link.href = `data:application/octet-stream;base64,${encodeURIComponent(content)}`;
  link.download = /\.\w+/.test(name) ? name : `${name}.${type}`;

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

['png', 'jpg', 'gif'].forEach(type => {
  var download = document.querySelector(`#${type}`);
  download.addEventListener('click', function() {
    var img = document.querySelector('#img');

    downloadImage('myImage', clearUrl(img.src), type);
  });
});
a gif image: <image id="img" src="data:image/gif;base64,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" />


<button id="png">Download PNG</button>
<button id="jpg">Download JPG</button>
<button id="gif">Download GIF</button>


3
Veuillez ajouter une brève explication à votre réponse, afin de la rendre pertinente pour la personne qui l'a posée
AGE

1
link.href = 'data: application / octet-stream,' + encodeURIComponent (adresse) cela corrompt le fichier et ne peut donc pas être ouvert, vous pouvez suggérer pourquoi
OM The Eternity

Ouais, cette réponse mérite d'être la meilleure! La partie manquante pour moi était la chose "cleanUrl", qui générait des données mal formées et cassait le fichier.
Iulian Pinzaru

3

En 2020, j'utilise Blob pour faire une copie locale de l'image, que le navigateur téléchargera sous forme de fichier. Vous pouvez le tester sur ce site .

entrez la description de l'image ici

(function(global) {
  const next = () => document.querySelector('.search-pagination__button-text').click();
  const uuid = () => Math.random().toString(36).substring(7);
  const toBlob = (src) => new Promise((res) => {
    const img = document.createElement('img');
    const c = document.createElement("canvas");
    const ctx = c.getContext("2d");
    img.onload = ({target}) => {
      c.width = target.naturalWidth;
      c.height = target.naturalHeight;
      ctx.drawImage(target, 0, 0);
      c.toBlob((b) => res(b), "image/jpeg", 0.75);
    };
    img.crossOrigin = "";
    img.src = src;
  });
  const save = (blob, name = 'image.png') => {
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.target = '_blank';
    a.download = name;
    a.click();
  };
  global.download = () => document.querySelectorAll('.search-content__gallery-results figure > img[src]').forEach(async ({src}) => save(await toBlob(src), `${uuid()}.png`));
  global.next = () => next();
})(window);

Il semble que ce code décode l'image dans un tampon de pixels (canevas) dans la mémoire du navigateur, puis la réencode en jpeg / png / gif, puis l'encapsule dans un data-uri qui, espérons-le, est ensuite stocké localement. Si tel est le cas, cela signifie que toutes les métadonnées du fichier image sont perdues. Le réencodage JPEG perdra également de la qualité et aura un rapport qualité / nombre d'octets plus mauvais. Pourtant, bon à savoir. Merci d'avoir partagé.
Stéphane Gourichon le

2

Essaye ça:

<a class="button" href="http://www.glamquotes.com/wp-content/uploads/2011/11/smile.jpg" download="smile.jpg">Download image</a>

0
<html>
<head>
<script type="text/javascript">
function prepHref(linkElement) {
    var myDiv = document.getElementById('Div_contain_image');
    var myImage = myDiv.children[0];
    linkElement.href = myImage.src;
}
</script>
</head>
<body>
<div id="Div_contain_image"><img src="YourImage.jpg" alt='MyImage'></div>
<a href="#" onclick="prepHref(this)" download>Click here to download image</a>
</body>
</html>

0

Vous pouvez télécharger directement ce fichier en utilisant la balise d'ancrage sans trop de code.
Copiez l'extrait et collez-le dans votre éditeur de texte et essayez-le ...!

<html>
<head>
</head>
<body>
   <div>
     <img src="https://upload.wikimedia.org/wikipedia/commons/1/1f/SMirC-thumbsup.svg" width="200" height="200">
      <a href="#" download="https://upload.wikimedia.org/wikipedia/commons/1/1f/SMirC-thumbsup.svg"> Download Image </a>
   </div>
</body>
</html>


2
veuillez ajouter plus de détails, par exemple où ce code peut être utilisé.
Maciej S.

-2

Qu'en est-il de l'utilisation de la fonction .click () et de la balise?

(Version compressée)

<a id="downloadtag" href="examplefolder/testfile.txt" hidden download></a>

<button onclick="document.getElementById('downloadtag').click()">Download</button>

Vous pouvez maintenant le déclencher avec js. Il n'ouvre pas non plus, comme d'autres exemples, des fichiers image et texte!

(version js-function)

function download(){
document.getElementById('downloadtag').click();
}
<!-- HTML -->
<button onclick="download()">Download</button>
<a id="downloadtag" href="coolimages/awsome.png" hidden download></a>


-5

Je l'ai trouvé

<a href="link/to/My_Image_File.jpeg" download>Download Image File</a>

N'a pas travaillé pour moi. Je ne sais pas pourquoi.

J'ai trouvé que vous pouvez inclure un ?download=trueparamètre à la fin de votre lien pour forcer un téléchargement. Je pense avoir remarqué que cette technique était utilisée par Google Drive.

Dans votre lien, incluez ?download=trueà la fin de votre href.

Vous pouvez également utiliser cette technique pour définir le nom de fichier en même temps.

Dans votre lien, incluez ?download=true&filename=My_Image_File.jpegà la fin de votre href.


2
? download = true est transmis à Google Drive pour indiquer à son serveur d'envoyer l'en-tête correct pour télécharger l'image. Ce n'est pas quelque chose qui fonctionnerait dans un autre environnement à moins qu'il ne soit spécifiquement configuré de cette façon.
muncherelli

-15

Vous n'avez pas besoin d'écrire js pour ce faire, utilisez simplement:

<a href="path_to/image.jpg" alt="something">Download image</a>

Et le navigateur lui-même téléchargera automatiquement l'image.

Si pour une raison quelconque cela ne fonctionne pas, ajoutez l'attribut de téléchargement. Avec cet attribut, vous pouvez définir un nom pour le fichier téléchargeable:

<a href="path_to/image.jpg" download="myImage">Download image</a>

Un lien vers l'image n'ouvrira l'image que dans la même fenêtre, sauf si votre navigateur est configuré différemment. L' downloadattribut n'est pas pris en charge dans tous les navigateurs.
Design by Adrian
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.