เบราว์เซอร์ / HTML บังคับให้ดาวน์โหลดรูปภาพจาก src =“ data: image / jpeg; base64 …”


86

ฉันกำลังสร้างภาพที่ฝั่งไคลเอ็นต์และแสดงด้วย HTML ดังนี้:

<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgM...."/>

ฉันต้องการเสนอความเป็นไปได้ในการดาวน์โหลดภาพที่สร้างขึ้น

ฉันจะรู้ได้อย่างไรว่าเบราว์เซอร์กำลังเปิดปุ่มหมุนบันทึกไฟล์ (หรือเพียงแค่ดาวน์โหลดรูปภาพเช่น chrome หรือ firefox ไปยังโฟลเดอร์ดาวน์โหลด) ซึ่งช่วยให้ผู้ใช้สามารถบันทึกภาพโดยไม่ต้องคลิกขวาและบันทึกตามภาพ

ฉันต้องการโซลูชันที่ไม่มีการโต้ตอบกับเซิร์ฟเวอร์ ดังนั้นฉันจึงทราบว่ามันจะเป็นไปได้ถ้าฉันอัปโหลดภาพก่อนแล้วจึงเริ่มการดาวน์โหลด

ขอบคุณมาก!

คำตอบ:


120

เพียงแค่แทนที่image/jpegด้วยapplication/octet-stream. ไคลเอนต์จะไม่รู้จัก URL เป็นทรัพยากรแบบอินไลน์และแจ้งให้ดาวน์โหลด

วิธีแก้ปัญหา JavaScript ง่ายๆคือ:

//var img = reference to image
var url = img.src.replace(/^data:image\/[^;]+/, 'data:application/octet-stream');
window.open(url);
// Or perhaps: location.href = url;
// Or even setting the location of an <iframe> element, 

อีกวิธีหนึ่งคือการใช้blob:URI:

var img = document.images[0];
img.onclick = function() {
    // atob to base64_decode the data-URI
    var image_data = atob(img.src.split(',')[1]);
    // Use typed arrays to convert the binary data to a Blob
    var arraybuffer = new ArrayBuffer(image_data.length);
    var view = new Uint8Array(arraybuffer);
    for (var i=0; i<image_data.length; i++) {
        view[i] = image_data.charCodeAt(i) & 0xff;
    }
    try {
        // This is the recommended method:
        var blob = new Blob([arraybuffer], {type: 'application/octet-stream'});
    } catch (e) {
        // The BlobBuilder API has been deprecated in favour of Blob, but older
        // browsers don't know about the Blob constructor
        // IE10 also supports BlobBuilder, but since the `Blob` constructor
        //  also works, there's no need to add `MSBlobBuilder`.
        var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder);
        bb.append(arraybuffer);
        var blob = bb.getBlob('application/octet-stream'); // <-- Here's the Blob
    }

    // Use the URL object to create a temporary URL
    var url = (window.webkitURL || window.URL).createObjectURL(blob);
    location.href = url; // <-- Download!
};

เอกสารที่เกี่ยวข้อง


1
ด้วยเหตุผลบางอย่างมันอาจจะขาดใน Chrome 19.0 เบต้า แต่มันใช้งานได้บน Chrome 18 และ Firefox ดังนั้นฉันจึงสบายดี มีความเป็นไปได้ที่จะตั้งชื่อไฟล์หรือไม่?
alex

ไม่มีวิธีตั้งชื่อไฟล์ใน data-URI แม้ว่าจะใช้canvas / Blobในการส่งออกข้อมูล แต่ก็ไม่สามารถตั้งชื่อไฟล์ได้ ฉันได้เพิ่มวิธีอื่นในคำตอบของฉันแล้ว (ฉันเดาว่าวิธีนี้จะใช้ได้ใน Chrome 19)
Rob W

2
คุณคิดว่าวิธีแรกจะเลิกใช้งานเพราะมันไม่ทำงานใน chrome 19 อีกต่อไปหรือไม่?
alex

1
ฉันไม่พบแหล่งที่มาที่เกี่ยวข้อง ฉันได้พบคำตอบนี้เช่นกันซึ่งแนะนำวิธีตั้งชื่อเริ่มต้นใน Chrome (จุดยึดเท่านั้นผู้ใช้ต้องคลิก)
Rob W

นอกจากนี้ยังพบโซลูชันนี้ - ดูเหมือนว่าจะเป็น Chrome เท่านั้นในตอนนี้ ขอบคุณสำหรับการสนับสนุน!
alex

98

คุณสามารถใช้แอตทริบิวต์การดาวน์โหลดบนแท็ก ...

<a href="data:image/jpeg;base64,/9j/4AAQSkZ..." download="filename.jpg"></a>

ดูเพิ่มเติม: https://developer.mozilla.org/en/HTML/element/a#attr-download


1
ฉันจะใช้วิธีนี้ได้อย่างไรเมื่อสร้างแหล่งที่มาของภาพแบบไดนามิก ฉันหมายความว่าฉันมีปุ่มดาวน์โหลดเมื่อผู้ใช้คลิกฉันจะทำการคำนวณสร้างภาพ base64 และ ... ฉันจะบังคับให้ดาวน์โหลดได้อย่างไร
Mikhail

ใน chrome ฉันไม่สามารถตั้งชื่อไฟล์โดยใช้วิธีนี้ ชื่อไฟล์ที่ดาวน์โหลดจะยังคงเป็น "ดาวน์โหลด" ไม่ว่าจะเกิดอะไรขึ้นก็ตาม สิ่งนี้เกิดขึ้นเฉพาะเมื่อใช้ data: image ...
cmaduro

5
ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ตามแอตทริบิวต์ 'ดาวน์โหลด' ของเว็บไซต์ W3Schools ไม่รองรับโดย IE, Safari และ Opera v <12 w3schools.com/tags/tryit.asp?filename=tryhtml5_a_download2อันที่จริงฉันได้ลองใช้กับ IE และ ไม่ได้ผล .... :(
Mirko Lugano

6
ในขณะแสดงความคิดเห็นdownloadแอตทริบิวต์นี้ยังไม่รองรับ Safari และ IE
TheCarver

1
มีข้อจำกัดความยาว base64 คุณไม่สามารถดาวน์โหลดภาพขนาดใหญ่โดยใช้วิธีนี้
Kiran Chenna

15

ฉันเดาว่าต้องใช้แท็กimg เป็นแท็กย่อยด้วยวิธีต่อไปนี้:

<a download="YourFileName.jpeg" href="data:image/jpeg;base64,iVBO...CYII=">
    <img src="data:image/jpeg;base64,iVBO...CYII="></img>
</a>

หรือ

<a download="YourFileName.jpeg" href="/path/to/OtherFile.jpg">
    <img src="/path/to/OtherFile.jpg"></img>
</a>

เพียงแค่ใช้แท็กที่อธิบายไว้ใน # 15 ไม่ได้ทำงานให้ฉันกับรุ่นล่าสุดของ Firefox และ Chrome แต่การวางข้อมูลภาพเดียวกันทั้งa.hrefและimg.srcแท็กทำงานให้ฉัน

จาก JavaScript สามารถสร้างได้ดังนี้:

var data = canvas.toDataURL("image/jpeg");

var img = document.createElement('img');
img.src = data;

var a = document.createElement('a');
a.setAttribute("download", "YourFileName.jpeg");
a.setAttribute("href", data);
a.appendChild(img);

var w = open();
w.document.title = 'Export Image';
w.document.body.innerHTML = 'Left-click on the image to save it.';
w.document.body.appendChild(a);

ไม่ใช่ว่าต้องมีแท็ก img อยู่ภายในเอกสาร MSDN ระบุว่าสามารถใช้ได้เฉพาะทรัพยากรที่ดาวน์โหลดมาแล้วเท่านั้น - ควรใช้งานได้ตราบเท่าที่คุณมีภาพที่มีข้อมูลเดียวกัน: base64 ที่ใดก็ได้ msdn.microsoft.com/en-us/library/cc848897.aspx - "ด้วยเหตุผลด้านความปลอดภัย URI ของข้อมูลถูก จำกัด ไว้ที่ทรัพยากรที่ดาวน์โหลดมาไม่สามารถใช้ URI ข้อมูลสำหรับการนำทางสำหรับการเขียนสคริปต์หรือเพื่อเติมองค์ประกอบของเฟรมหรือ iframe"
Dimitar Christoff

5

ลองดูที่FileSaver.js มีsaveAsฟังก์ชั่นที่มีประโยชน์ซึ่งดูแลนิสัยใจคอของเบราว์เซอร์ส่วนใหญ่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.