web-dev-qa-db-fra.com

Forcer le téléchargement d'une image à l'aide de Javascript

Je souhaite savoir s’il est possible de créer un script avec Javascript/jQuery pour télécharger (ouvrir une boîte de dialogue de téléchargement) une image afin que le navigateur ne l’affiche pas.

16
Nathan Campos

Vous devez utiliser un script côté serveur pour cela. Recherche sur stackoverflow .

Alternativement, votre serveur peut vous permettre de modifier les en-têtes de manière dynamique via la configuration.

Solution Apache avec mod_headers

Placez vos images téléchargeables dans un répertoire. Dans ce répertoire, créez un fichier .htaccess avec le contenu suivant:

SetEnvIf Request_URI "([^/]+\.jpg)$" REQUESTED_IMAGE_BASENAME=$1
SetEnvIf Request_URI "([^/]+\.png)$" REQUESTED_IMAGE_BASENAME=$1
Header set Content-Disposition "attachment; filename=\"%{REQUESTED_IMAGE_BASENAME}e\"" env=REQUESTED_IMAGE_BASENAME

Demande d'essai:

HEAD /test/Water%20lilies.jpg HTTP/1.1
Host: localhost

Réponse de test:

HTTP/1.1 200 OK
Date: Sat, 23 Jul 2011 09:03:52 GMT
Server: Apache/2.2.17 (Win32)
Last-Modified: Thu, 23 Aug 2001 14:00:00 GMT
ETag: "26000000017df3-14752-38c32e813d800"
Accept-Ranges: bytes
Content-Length: 83794
Content-Disposition: attachment; filename="Water lilies.jpg"
Content-Type: image/jpeg

Solution HTML5

Vous pouvez utiliser l’attribut HTML5 download sur les ancres :

<p>Example 1<br>
   <a href="http://dummyimage.com/600x400/000/fff.png" download>Download this image</a></p>

<p>Example 2<br>
   <a href="http://dummyimage.com/600x400/000/fff.png" download="alternate-filename.png"><img
       src="http://dummyimage.com/150x100/000/fff.png"></a></p>

35
Salman A

J'ai mis au point un moyen purement JavaScript pour forcer le téléchargement de l'image, avec les restrictions suivantes:

  1. L'utilisation de HTML5 ne fonctionnait donc pas du tout dans les navigateurs IE avant IE9.
  2. Dans IE (même 9), limité à de très petites images, en raison de la limite de longueur de l'URL.
  3. Le nom de l'image (lorsqu'il est enregistré sur la machine) ne peut pas être déterminé dans le code. Dans Chrome, il s'agira simplement de "télécharger" sans extension et dans Firefox, ce sera comme une chaîne de caractères avec l'extension ".part" - dans tous les cas, l’utilisateur devra renommer le fichier pour le rendre utilisable.
  4. Ne peut télécharger des images que dans le même domaine - même politique d'origine.

Les restrictions ci-dessus (en particulier la troisième) rendent plus ou moins cela inutile mais néanmoins, l'idée "de base" est fonctionne et j'espère qu'à un moment donné, il sera possible de déterminer le nom du fichier, puis il deviendra beaucoup plus utile.

Voici le code:

function DownloadImage(imageURL) {
    var oImage = document.getElementById(imageURL);
    var canvas = document.createElement("canvas");
    document.body.appendChild(canvas);
    if (typeof canvas.getContext == "undefined" || !canvas.getContext) {
        alert("browser does not support this action, sorry");
        return false;
    }

    try {
        var context = canvas.getContext("2d");
        var width = oImage.width;
        var height = oImage.height;
        canvas.width = width;
        canvas.height = height;
        canvas.style.width = width + "px";
        canvas.style.height = height + "px";
        context.drawImage(oImage, 0, 0, width, height);
        var rawImageData = canvas.toDataURL("image/png;base64");
        rawImageData = rawImageData.replace("image/png", "image/octet-stream");
        document.location.href = rawImageData;
        document.body.removeChild(canvas);
    }
    catch (err) {
        document.body.removeChild(canvas);
        alert("Sorry, can't download");
    }

    return true;
}

Comme vous pouvez le constater, l’astuce consiste à dessiner l’image dans un objet canvas, obtenir les données binaires brutes de l’image, puis forcer le téléchargement en utilisant le type mime image/octet-stream et en modifiant l’emplacement du navigateur.

Un exemple d'utilisation suit également.

HTML:

<image id="myimage" src="Penguins.jpg" />
<button type="btnDownload" rel="myimage">Download</button>

JavaScript:

window.onload = function() {
    var arrButtons = document.getElementsByTagName("button");
    for (var i = 0; i < arrButtons.length; i++) {
        var oButton = arrButtons[i];
        var sRelatedImage = oButton.getAttribute("rel");
        if (sRelatedImage && sRelatedImage.length > 0) {
            oButton.onclick = function() {
                HandleRelatedImage(this, sRelatedImage);
            }
        }
    }
};

function HandleRelatedImage(oButton, sRelatedImage) {
    var oImage = document.getElementById(sRelatedImage);
    if (!oImage) {
        alert("related image '" + sRelatedImage + "' does not exist");
        return false;
    }

    return DownloadImage(sRelatedImage);
}

Cela permet "d'attacher" le bouton de téléchargement à chaque image existante en attribuant l'attribut rel du bouton à l'ID d'image - le code fera le reste et joindra les événements de clic réels.

En raison de la même politique Origin, je ne peux pas poster d’exemples en direct sur jsFiddle. Ils utilisent un domaine "sandbox" pour exécuter les scripts.

14
Shadow Wizard

C'est totalement possible. Il suffit d’encoder l’image en Base64 puis de créer un window.open avec une URL de type data:image/jpg,Base64,....

0
buley

Je suppose que vous voulez dire quelque chose comme ça:

Accédez à l'URL dans le navigateur. L'URL est: http://example.com/image.png

et au lieu d'afficher, le navigateur vous invite à enregistrer l'image?

Je suis à peu près sûr que vous ne pouvez pas forcer cela avec JavaScript et que vous aurez besoin d'un langage côté serveur pour contrôler les en-têtes. Et même à ce stade, vous ne pouvez pas forcer le navigateur à le télécharger, chaque utilisateur réagira différemment selon les en-têtes que vous pourrez envoyer.

EDIT: Je semble me souvenir que l'en-tête étant Content-Disposition: attachment;

0
Anthony Sottile