ดาวน์โหลดไฟล์ url ข้อมูล


127

ฉันกำลังเล่นกับแนวคิดในการสร้างยูทิลิตี้ zip / unzip ที่ใช้ JavaScript ซึ่งทุกคนสามารถเข้าถึงได้จากเบราว์เซอร์ พวกเขาสามารถลาก zip ลงในเบราว์เซอร์ได้โดยตรงจากนั้นมันจะช่วยให้ดาวน์โหลดไฟล์ทั้งหมดภายใน นอกจากนี้ยังสามารถสร้างไฟล์ zip ใหม่โดยลากไฟล์แต่ละไฟล์เข้ามา

ฉันรู้ว่ามันจะดีกว่าถ้าทำบนเซิร์ฟเวอร์ แต่โปรเจ็กต์นี้ก็เพื่อความสนุก

การลากไฟล์ลงในเบราว์เซอร์ควรจะง่ายพอหากฉันใช้ประโยชน์จากวิธีการต่างๆที่มีอยู่ (สไตล์ Gmail)

หวังว่าการเข้ารหัส / ถอดรหัสน่าจะใช้ได้ ฉันเคยเห็นไลบรารี zip ของ as3 ดังนั้นฉันแน่ใจว่าฉันน่าจะใช้ได้ดี

ปัญหาของฉันคือการดาวน์โหลดไฟล์ในตอนท้าย

window.location = 'data:jpg/image;base64,/9j/4AAQSkZJR....' 

ใช้งานได้ดีใน firefox แต่ไม่ใช่ใน chrome

ฉันสามารถฝังไฟล์เป็นรูปภาพได้ใน chrome โดยใช้<img src="data:jpg/image;ba.." />แต่ไฟล์ไม่จำเป็นต้องเป็นรูปภาพ อาจเป็นรูปแบบใดก็ได้

ใครสามารถคิดวิธีแก้ปัญหาอื่นหรือวิธีแก้ปัญหาบางอย่าง?


คำตอบ:


42

ไอเดีย:

  • ลอง<a href="data:...." target="_blank">(ยังไม่ทดสอบ)

  • ใช้downloadifyแทน data URLs (ใช้ได้กับ IE ด้วย)


@jcubic ขอบคุณสำหรับการชี้ให้เห็นลิงก์ที่ตายแล้ว ตำแหน่งดาวน์โหลดใหม่น่าจะเป็นgithub.com/dcneiner/Downloadify
Pekka

ถ้าคุณไม่สามารถใช้ Flash แต่จะมีการทำงานเป็นส่วนประกอบ Java ฝั่งเซิร์ฟเวอร์คุณสามารถใช้นี้github.com/suprememoocow/databounce ใช้ Servlet เพื่อ 'ตีกลับ' ข้อมูลจากไคลเอนต์ มันค่อนข้างง่ายที่จะใช้เคล็ดลับเดียวกันในเทคโนโลยีฝั่งเซิร์ฟเวอร์อื่น ๆ เช่น Python, ASP.NET และอื่น ๆ
Andrew Newdigate

มีวิธีทำแบบไม่ใช้แฟลชไหม? URL ข้อมูลสำหรับเบราว์เซอร์ทั้งหมดยกเว้น IE และ ActiveX foo สำหรับ IE บางประเภท? (วิธีนี้ฉันจัดการเพื่อเล่นเพลงโดยไม่ใช้แฟลช: เสียง HTML5 สำหรับเบราว์เซอร์ทั้งหมดยกเว้น IE และ ActiveX สำหรับ IE)
panzi

Downloadify คาดว่าจะเล่นแฟลชในเบราว์เซอร์ หากผู้ใช้ไม่มีโปรแกรมเล่นแฟลชไฟล์จะไม่ดาวน์โหลด
Jeevanandan J

187

หากคุณต้องการตั้งชื่อที่แนะนำให้กับไฟล์ (แทนค่าเริ่มต้น "ดาวน์โหลด") คุณสามารถใช้สิ่งต่อไปนี้ใน Chrome, Firefox และ IE บางเวอร์ชัน:

function downloadURI(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  delete link;
}

และตัวอย่างต่อไปนี้แสดงการใช้งาน:

downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");

6
คุณสามารถทำให้ง่ายขึ้นโดยlink.click()ใช้แทนeventFireฟังก์ชันของคุณ... jsfiddle.net/ARTsinn/Ezx5m
yckart

3
ทางออกที่ดี แต่หลังจากนั้นลิงค์จะกลายเป็นอะไร?
webshaker

6
ตัวแปร 'ลิงค์' ออกไปนอกขอบเขตที่ส่วนท้ายของฟังก์ชัน (โปรดทราบว่าเราไม่เคยเพิ่มเข้าไปในโดม) ดังนั้นจะถูกเก็บรวบรวมในไม่ช้าหลังจากนั้น
owencm

8
ใช้งานได้ใน Chrome เท่านั้น หากคุณต้องการให้ทำงานใน Firefox / IE ดูคำตอบจาก @MartinoDino
TrueWill

1
ฉันลองใช้download.jsตามที่แนะนำที่นี่และดูเหมือนว่าจะใช้งานได้ :)
joaorodr84

56

function download(dataurl, filename) {
  var a = document.createElement("a");
  a.href = dataurl;
  a.setAttribute("download", filename);
  a.click();
}

download("data:text/html,HelloWorld!", "helloWorld.txt");

หรือ:

function download(url, filename) {
fetch(url).then(function(t) {
    return t.blob().then((b)=>{
        var a = document.createElement("a");
        a.href = URL.createObjectURL(b);
        a.setAttribute("download", filename);
        a.click();
    }
    );
});
}

download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");


คลิกเหตุการณ์บนองค์ประกอบที่ไม่อยู่: D ไม่จำเป็นต้องต่อท้าย
Zibri

1
ใช่. คุณสามารถเรียก a.click () หลังจากที่คุณสร้างองค์ประกอบ 'a' แล้วตั้งค่า href
user1709076

ในอดีตการเรียก a.click () โดยตรงจะใช้ไม่ได้ แต่ทำงานร่วมกับเหตุการณ์ ตอนนี้ทั้งคู่ทำงาน
Zibri

1
สิ่งนี้ใช้ได้กับเบราว์เซอร์ที่ทันสมัยส่วนใหญ่ แต่ฉันควรทราบว่าการต่อท้ายเอกสารนั้นจำเป็นต้องลบออกเพื่อรองรับเบราว์เซอร์รุ่นเก่าบางตัว
owencm

3
ควรใช้โซลูชันที่สองของคุณเมื่อใดก็ตามที่ dataUri มีขนาดใหญ่เกินไป (ขึ้นอยู่กับเบราว์เซอร์ แต่ Chrome ไม่ยอมรับ Uri หลายเมกะไบต์จากประสบการณ์ของฉัน) ดูยังstackoverflow.com/questions/38781968/...
neural5torm

27

ต้องการแบ่งปันประสบการณ์ของฉันและช่วยคนที่ติดอยู่กับการดาวน์โหลดที่ไม่ทำงานใน Firefox และอัปเดตคำตอบของปี 2014 ตัวอย่างข้อมูลด้านล่างนี้จะใช้ได้ทั้งใน firefox และ chrome และจะยอมรับชื่อไฟล์:

  // Construct the <a> element
  var link = document.createElement("a");
  link.download = thefilename;
  // Construct the uri
  var uri = 'data:text/csv;charset=utf-8;base64,' + someb64data
  link.href = uri;
  document.body.appendChild(link);
  link.click();
  // Cleanup the DOM
  document.body.removeChild(link);

4
น่าเสียดายที่มันใช้ไม่ได้ใน Safari Safari ดูเหมือนจะไม่รู้จักdownloadแอตทริบิวต์ ขอบคุณอย่างไรก็ตามนี่อยู่ใกล้ที่สุดเท่าที่จะทำได้ในขณะนี้
Moritz Petersen

สิ่งนี้ทำให้หน้าต่างเปลี่ยนเส้นทางไปยังค่า href สำหรับฉันใน IE 11. prevetDefault (); ไม่หยุดพฤติกรรมใน IE
b_dubb

1
ขอบคุณเช่นกันหากbtoaไม่ได้กำหนดไว้ (เช่นในโหนด eslinted frontend project) const btxt = new Buffer(text).toString('base64'); const uri = 'data:text/csv;charset=utf-8;base64,' + btxt + ';'
Ivan Borshchov

2
การลบลิงก์นั้นไม่มีจุดหมายมันจะออกนอกขอบเขตในบรรทัดถัดไปและจะถูกเก็บรวบรวมขยะไม่ใช่เป้าหมายที่ถูกต้องสำหรับการลบ
macdja38

1
ไม่ต้องการ document.body.appendChild ... ดูคำตอบของฉันstackoverflow.com/a/45905238/236062
Zibri

13

นี่คือโซลูชัน JavaScript บริสุทธิ์ที่ฉันทดสอบการทำงานใน Firefox และ Chrome แต่ไม่ใช่ใน Internet Explorer:

function downloadDataUrlFromJavascript(filename, dataUrl) {

    // Construct the 'a' element
    var link = document.createElement("a");
    link.download = filename;
    link.target = "_blank";

    // Construct the URI
    link.href = dataUrl;
    document.body.appendChild(link);
    link.click();

    // Cleanup the DOM
    document.body.removeChild(link);
    delete link;
}

พบโซลูชันข้ามเบราว์เซอร์จนถึงปัจจุบัน:

ดาวน์โหลด -> ต้องใช้แฟลช

databounce -> ทดสอบใน IE 10 และ 11 แล้วและไม่ได้ผลสำหรับฉัน ต้องใช้ servlet และการปรับแต่งบางอย่าง (ตรวจพบเนวิเกเตอร์ไม่ถูกต้องฉันต้องตั้งค่า IE ในโหมดความเข้ากันได้เพื่อทดสอบ, ชุดอักขระเริ่มต้นใน servlet, อ็อบเจ็กต์ JavaScript ที่มีเส้นทาง servlet ที่ถูกต้องสำหรับพา ธ สัมบูรณ์ ... ) สำหรับเบราว์เซอร์ที่ไม่ใช่ IE จะเปิดไฟล์ในหน้าต่างเดียวกัน

download.js -> http://danml.com/download.htmlไลบรารีอื่นที่คล้ายกัน แต่ไม่ได้ทดสอบ อ้างว่าเป็น JavaScript บริสุทธิ์ไม่ต้องใช้ servlet หรือ Flash แต่ไม่ทำงานบน IE <= 9


download.js ค่อนข้างดี เพิ่งตรวจสอบอย่างรวดเร็วบน IE11 ก็ใช้งานได้ ขอบคุณมาก!
Ricky Jiao

12

มีวิธีแก้ปัญหาหลายวิธี แต่ขึ้นอยู่กับ HTML5 และยังไม่ได้นำไปใช้อย่างสมบูรณ์ในบางเบราว์เซอร์ ตัวอย่างด้านล่างได้รับการทดสอบใน Chrome และ Firefox (ใช้งานได้บางส่วน)

  1. ตัวอย่างแคนวาสพร้อมบันทึกลงในไฟล์รองรับ เพียงตั้งค่าของคุณdocument.location.hrefเป็น URI ข้อมูล
  2. Anchor ดาวน์โหลดตัวอย่าง ใช้<a href="your-data-uri" download="filename.txt">เพื่อระบุชื่อไฟล์

3
ตัวอย่างแคนวาสนำไปสู่ ​​404
Karel Bílek

แอตทริบิวต์การดาวน์โหลดใช้งานได้สำหรับฉันสำหรับ URL ข้อมูล pdf ใน Chrome และซาฟารีมือถือ
bbsimonbb

7

เมื่อรวมคำตอบจาก @owencm และ @ Chazt3n ฟังก์ชันนี้จะอนุญาตให้ดาวน์โหลดข้อความจาก IE11, Firefox และ Chrome (ขออภัยฉันไม่สามารถเข้าถึง Safari หรือ Opera ได้ แต่โปรดเพิ่มความคิดเห็นหากคุณลองแล้วได้ผล)

initiate_user_download = function(file_name, mime_type, text) {
    // Anything but IE works here
    if (undefined === window.navigator.msSaveOrOpenBlob) {
        var e = document.createElement('a');
        var href = 'data:' + mime_type + ';charset=utf-8,' + encodeURIComponent(text);
        e.setAttribute('href', href);
        e.setAttribute('download', file_name);
        document.body.appendChild(e);
        e.click();
        document.body.removeChild(e);
    }
    // IE-specific code
    else {
        var charCodeArr = new Array(text.length);
        for (var i = 0; i < text.length; ++i) {
            var charCode = text.charCodeAt(i);
            charCodeArr[i] = charCode;
        }
        var blob = new Blob([new Uint8Array(charCodeArr)], {type: mime_type});
        window.navigator.msSaveOrOpenBlob(blob, file_name);
    }
}

// Example:
initiate_user_download('data.csv', 'text/csv', 'Sample,Data,Here\n1,2,3\n');

1

สำหรับใครก็ตามที่มีปัญหาใน IE:

โปรดโหวตคำตอบที่นี่โดย Yetti: ประหยัดผ้าใบใน IE

dataURItoBlob = function(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

var blob = dataURItoBlob(uri);
window.navigator.msSaveOrOpenBlob(blob, "my-image.png");

0

ปัญหาของคุณโดยพื้นฐานแล้ว "ไม่ใช่เบราว์เซอร์ทั้งหมดที่รองรับสิ่งนี้"

คุณสามารถลองวิธีแก้ปัญหาชั่วคราวและให้บริการไฟล์ที่คลายซิปจากออบเจ็กต์ Flash แต่คุณจะสูญเสียความบริสุทธิ์ของ JS เท่านั้น (อย่างไรก็ตามฉันไม่แน่ใจว่าขณะนี้คุณสามารถ "ลากไฟล์ไปยังเบราว์เซอร์" ได้โดยไม่ต้องใช้วิธีแก้ปัญหา Flash บางประเภทหรือไม่ - นั่นอาจเป็นฟีเจอร์ HTML5 หรือไม่)

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