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

Amit
la source
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
1
Double possible: stackoverflow.com/questions/2408146/… ?
Karl-André Gagnon
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
la source
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);
Somnolent
la source
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();
}
iXs
la source
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>

Riley Bell
la source
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

Emerica
la source
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);     
Sadi
la source
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>

hakobpogh
la source
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);
Petr Tripolsky
la source
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>
Muhammad Awais
la source
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>
Génie Zardari
la source
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>

vinod
la source
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>

Murmure empoisonné
la source
-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.

Mufasa
la source
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>
António Regadas
la source
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