使用 Javascript 强制下载图像

发布于 2024-11-25 14:01:20 字数 73 浏览 1 评论 0原文

我想知道是否有任何方法可以使用 Javascript/jQuery 制作脚本来下载(打开下载对话框)图像,这样浏览器就不会只显示它。

I want to know if there is any way to make a script using Javascript/jQuery to download (open a download dialog) a image so the browser won't just show it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

薄暮涼年 2024-12-02 14:01:20

为此,您需要使用服务器端脚本。 在 stackoverflow 上搜索

或者,您的服务器可能允许您通过配置动态更改标头。

Apache 解决方案与 mod_headers

将可下载的图像放在一个目录中。在此目录中,创建一个包含以下内容的 .htaccess 文件:

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

测试请求:

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

测试响应:

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

HTML5 解决方案

您可以 在锚点上使用 HTML5 download 属性

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

You need to use server-side scripting for this. Search on stackoverflow.

Alternately, your server might allow you to alter headers dynamically via configuration.

Apache solution with mod_headers

Place your downloadable images in a directory. Inside this directory, create a .htaccess file with the following contents:

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

Test Request:

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

Test Response:

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

HTML5 Solution

You can use the HTML5 download attribute on anchors:

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

老街孤人 2024-12-02 14:01:20

我想出了纯 JavaScript 的方法来强制下载图像,但有以下限制:

  1. 使用 HTML5,因此在 IE9 之前的 IE 浏览器中根本不起作用。
  2. 在 IE(甚至 9)中,由于 URL 长度限制,只能显示非常小的图像。
  3. 图像名称(保存到计算机时)无法在代码中确定,在 Chrome 中,它只是“下载”,没有扩展名,而在 Firefox 中,它看起来像带有“.part”扩展名的乱码字符串 - 无论哪种方式,用户必须重命名该文件才能使其可用。
  4. 只能下载同一域中的图像 - 同源策略。

上述限制(尤其是第三个)或多或少使这个毫无用处,但“核心”想法正在发挥作用,希望在将来的某个时候可以确定文件名,然后它将变得更加有用。

代码如下:

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

如您所见,技巧是将图像绘制到canvas对象中,获取图像的原始二进制数据,然后使用image/octet-stream强制下载code> mime 类型并更改浏览器位置。

使用示例也如下。

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

这允许通过将按钮的 rel 属性分配给图像 ID,将下载按钮“附加”到每个现有图像 - 代码将完成其余工作并附加实际的点击事件。

由于同源政策无法在 jsFiddle 上发布实时示例 - 他们正在使用“沙箱”域来执行脚本。

I have come up with pure JavaScript way to force download of image, with the following restrictions:

  1. Using HTML5 so not working at all in IE browsers before IE9.
  2. In IE (even 9) limited to very small images, due to URL length limit.
  3. The image name (when saved to machine) can't be determined in the code, in Chrome it will be just "download" without extension and in Firefox it will be what looks like jibberish string with ".part" extension - either way, user will have to rename the file to make it usable.
  4. Can only download images in the same domain - same origin policy.

The above restrictions (especially the third) more or less renders this useless but still, the "core" idea is working and hopefully at some point in the future it will be possible to determine file name then it will become much more useful.

Here is the 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;
}

As you can see, the trick is drawing the image into canvas object, get the raw binary data of the image then force download by using image/octet-stream mime type and changing the browser location.

Usage sample follows as well.

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

This allows to "attach" download button to every existing image by assigning the rel attribute of the button to the image ID - the code will do the rest and attach the actual click events.

Due to the same origin policy can't post live example at jsFiddle - they're using "sandbox" domain to execute the scripts.

我爱人 2024-12-02 14:01:20

这是一个使用 HTML5“下载”属性的简单解决方案:

document.getElementById('download').click();
<a id="download" href="https://docs.google.com/uc?id=0B0jH18Lft7ypSmRjdWg1c082Y2M" download hidden></a>

If it can find the picture it will download a cat picture.

Here's a simple solution that uses the HTML5 'download' attribute:

document.getElementById('download').click();
<a id="download" href="https://docs.google.com/uc?id=0B0jH18Lft7ypSmRjdWg1c082Y2M" download hidden></a>

If it can find the picture it will download a cat picture.

ˇ宁静的妩媚 2024-12-02 14:01:20

这是完全有可能的。只需将图像编码为 Base64,然后使用 data:image/jpg,Base64,... 样式的 url 执行 window.open 即可。

This is totally possible. Just encode the image as Base64 then do a window.open with a data:image/jpg,Base64,...-style url.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文