Tải xuống tập tin url dữ liệu


126

Tôi đang chơi với ý tưởng tạo ra một tiện ích zip / giải nén hoàn toàn dựa trên JavaScript mà bất kỳ ai cũng có thể truy cập từ trình duyệt. Họ chỉ có thể kéo zip của họ trực tiếp vào trình duyệt và nó sẽ cho phép họ tải xuống tất cả các tệp trong đó. Họ cũng có thể tạo các tệp zip mới bằng cách kéo các tệp riêng lẻ vào.

Tôi biết sẽ tốt hơn nếu làm điều đó trên máy chủ, nhưng dự án này chỉ là một chút thú vị.

Kéo tập tin vào trình duyệt sẽ đủ dễ dàng nếu tôi tận dụng các phương thức khác nhau có sẵn. (Kiểu Gmail)

Mã hóa / giải mã hy vọng sẽ ổn. Tôi đã thấy một số thư viện zip as3 vì vậy tôi chắc chắn rằng tôi sẽ ổn với điều đó.

Vấn đề của tôi là tải xuống các tập tin vào cuối.

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

Điều này hoạt động tốt trong firefox nhưng không phải trong chrome.

Tôi có thể nhúng các tệp dưới dạng hình ảnh tốt trong chrome bằng cách sử dụng <img src="data:jpg/image;ba.." />, nhưng các tệp không nhất thiết phải là hình ảnh. Chúng có thể là bất kỳ định dạng.

Bất cứ ai cũng có thể nghĩ về một giải pháp khác hoặc một số cách giải quyết?


Thật không may, sự hỗ trợ hiện tại khá hạn chế
Casebash

Câu trả lời:


42

Ý tưởng:

  • Hãy thử một <a href="data:...." target="_blank">(chưa được kiểm tra)

  • Sử dụng downloadify thay vì URL dữ liệu (cũng sẽ hoạt động với IE)


@jcubic cảm ơn vì đã chỉ ra đường link chết. Vị trí tải xuống mới dường như là github.com/dcneiner/D
Pekka

Nếu bạn không thể sử dụng Flash nhưng đang chạy một thành phần phía máy chủ Java, bạn có thể sử dụng: github.com/suprememoocow/databounce . Nó sử dụng một Servlet để 'trả lại' dữ liệu từ máy khách. Sẽ khá dễ dàng để thực hiện thủ thuật tương tự trong các công nghệ phía máy chủ khác, chẳng hạn như Python, ASP.NET, v.v.
Andrew Newdigate

Có cách nào để làm điều đó mà không cần flash? URL dữ liệu cho tất cả các trình duyệt trừ IE và một số loại ActiveX foo cho IE? (Cách này tôi đã quản lý để phát nhạc mà không cần flash: âm thanh HTML5 cho tất cả các trình duyệt trừ IE và ActiveX cho IE.)
panzi

Downloadify mong đợi trình phát flash trong trình duyệt. Nếu người dùng không có trình phát flash, thì tệp sẽ không tải xuống
Jeevanandan J

186

Nếu bạn cũng muốn đặt tên được đề xuất cho tệp (thay vì 'tải xuống' mặc định), bạn có thể sử dụng các mục sau trong Chrome, Firefox và một số phiên bản 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;
}

Và ví dụ sau đây cho thấy nó sử dụng:

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

6
Bạn có thể đơn giản hóa điều đó bằng link.click()thay vì eventFirechức năng của mình ... jsfiddle.net/ARTsinn/Ezx5m
yckart

3
Giải pháp tốt đẹp. Nhưng liên kết trở thành gì sau?
webshaker

6
Biến 'liên kết' đi ra khỏi phạm vi ở cuối hàm (lưu ý chúng tôi không bao giờ thêm nó vào dom) vì vậy sẽ được thu gom rác ngay sau đó.
owencm

8
Điều này chỉ hoạt động trong Chrome. Nếu bạn muốn nó hoạt động trong Firefox / IE, hãy xem câu trả lời từ @MartinoDino.
TrueWill

1
Tôi đã thử với download.js , như được đề xuất ở đây và nó dường như hoạt động. :)
joaorodr84

53

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

hoặc là:

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


nhấp vào sự kiện trên phần tử không tồn tại: D không cần cho phần phụ.
Zibri

1
Đúng. bạn có thể chỉ cần gọi a.click () sau khi bạn đã tạo phần tử 'a', rồi đặt href.
dùng1709076

trong quá khứ, gọi a.click () trực tiếp sẽ không hoạt động nhưng nó hoạt động với sự kiện. Bây giờ cả hai đều làm việc.
Zibri 17/03/19

1
Điều này hoạt động trong hầu hết các trình duyệt hiện đại, nhưng tôi lưu ý rằng việc thêm vào tài liệu sau đó xóa là cần thiết để hỗ trợ một số trình duyệt cũ hơn.
owencm

3
Giải pháp thứ hai của bạn nên được sử dụng bất cứ khi nào dataUri trở nên quá lớn (tùy thuộc vào trình duyệt, nhưng Chrome không chấp nhận Uri nhiều megabyte theo kinh nghiệm của tôi). Xem thêm stackoverflow.com/questions/38781968/ .
neural5torm

27

Muốn chia sẻ kinh nghiệm của tôi và giúp ai đó bị kẹt khi tải xuống không hoạt động trong Firefox và cập nhật câu trả lời cho năm 2014. Đoạn mã dưới đây sẽ hoạt động trong cả firefox và chrome và nó sẽ chấp nhận tên tệp:

  // 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
Thật không may, nó không hoạt động trong Safari. Safari dường như không nhận ra downloadthuộc tính. Dù sao cũng cảm ơn, điều này gần đến mức tôi có thể nhận được vào lúc này.
Moritz Petersen

điều này khiến cửa sổ chuyển hướng đến giá trị href cho tôi trong IE 11. prevetDefault (); không dừng hành vi trong IE
b_dubb

1
Cũng cảm ơn, nếu btoakhông được xác định (ví dụ: trong dự án frontend eslinted) const btxt = new Buffer(text).toString('base64'); const uri = 'data:text/csv;charset=utf-8;base64,' + btxt + ';'
Ivan Borshchov

2
xóa liên kết là vô nghĩa, nó đi ra khỏi phạm vi trên dòng tiếp theo và sẽ được thu gom rác, đó không phải là mục tiêu hợp lệ để xóa.
macdja38

1
không cần tài
liệu.body.appendChild

13

Đây là một giải pháp JavaScript thuần túy mà tôi đã thử nghiệm làm việc trong Firefox và Chrome nhưng không có trong 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;
}

Các giải pháp trình duyệt chéo được tìm thấy cho đến bây giờ:

downloadify -> Yêu cầu Flash

databounce -> Đã thử nghiệm trong IE 10 và 11 và không hoạt động đối với tôi. Yêu cầu một servlet và một số tùy chỉnh. .

download.js -> http://danml.com/doad.html Một thư viện khác tương tự nhưng chưa được thử nghiệm. Khẳng định là JavaScript thuần túy, không yêu cầu servlet hay Flash, nhưng không hoạt động trên IE <= 9.


download.js là khá tốt. Chỉ cần kiểm tra nhanh trên IE11, nó hoạt động. Cảm ơn rất nhiều!
Ricky Jiao

12

Có một số giải pháp nhưng chúng phụ thuộc vào HTML5 và chưa được triển khai hoàn toàn trong một số trình duyệt. Các ví dụ dưới đây đã được thử nghiệm trong Chrome và Firefox (một phần hoạt động).

  1. Ví dụ Canvas với lưu để hỗ trợ tập tin. Chỉ cần đặt document.location.hrefURI dữ liệu của bạn .
  2. Neo ví dụ tải về . Nó sử dụng <a href="your-data-uri" download="filename.txt">để xác định tên tập tin.

3
ví dụ canvas dẫn đến 404
Karel Bílek

Thuộc tính tải xuống đang hoạt động đối với tôi, đối với url dữ liệu pdf trong chrome và safari di động.
bbsimonbb

7

Kết hợp các câu trả lời từ @owencm và @ Chazt3n, chức năng này sẽ cho phép tải xuống văn bản từ IE11, Firefox và Chrome. (Xin lỗi, tôi không có quyền truy cập vào Safari hoặc Opera, nhưng vui lòng thêm nhận xét nếu bạn thử và nó hoạt động.)

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

Đối với bất kỳ ai có vấn đề trong IE:

Vui lòng upvote câu trả lời ở đây bởi Yetti: lưu canvas tại địa phương trong 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

Vấn đề của bạn về cơ bản là "không phải tất cả các trình duyệt sẽ hỗ trợ điều này".

Bạn có thể thử một cách giải quyết và phục vụ các tệp được giải nén từ một đối tượng Flash, nhưng sau đó bạn sẽ mất độ tinh khiết chỉ có JS (dù sao, tôi không chắc liệu hiện tại bạn có thể "kéo tệp vào trình duyệt" mà không cần một cách giải quyết Flash nào không - đó có phải là một tính năng HTML5 không?)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.