Bağlantı olmadan JavaScript blob dosya adı


189

Window.location üzerinden indirmeye zorladığınızda JavaScript'te bir blob dosyasının adını nasıl ayarlarsınız?

function newFile(data) {
    var json = JSON.stringify(data);
    var blob = new Blob([json], {type: "octet/stream"});
    var url  = window.URL.createObjectURL(blob);
    window.location.assign(url);
}

Yukarıdaki kodu çalıştırmak, aşağıdaki gibi bir sayfa yenilemesi olmadan anında bir dosya indirir:

bfefe410-8d9c-4883-86c5-d76c50a24a1d

Bunun yerine dosya adını my-download.json olarak ayarlamak istiyorum .

Yanıtlar:


313

Farkında olduğum tek yol FileSaver.js tarafından kullanılan hile :

  1. Gizli bir <a>etiket oluşturun .
  2. Onun Set hrefBlob URL'sini niteliği.
  3. downloadÖzniteliğini dosya adına ayarlayın .
  4. <a>Etiketi tıklayın .

İşte basitleştirilmiş bir örnek ( jsfiddle ):

var saveData = (function () {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, fileName) {
        var json = JSON.stringify(data),
            blob = new Blob([json], {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());

var data = { x: 42, s: "hello, world", d: new Date() },
    fileName = "my-download.json";

saveData(data, fileName);

Bu örneği sadece fikri göstermek için yazdım, üretim kodunda FileSaver.js kullanın.

notlar

  • Daha eski tarayıcılar, HTML5'in bir parçası olduğu için "indirme" özelliğini desteklemez.
  • Bazı dosya biçimlerinin tarayıcı tarafından güvenli olmadığı kabul edilir ve indirme başarısız olur. Txt uzantılı JSON dosyalarını kaydetmek benim için çalışıyor.

2
@AshBlue "İndirme" özelliğinin HTML5 olması gerekiyor. Kodum
kol

1
İlginçtir, tekrar tekrar bu şekilde bir txt indirmeye çalışırsanız (jsfiddle.net üzerindeki Çalıştır düğmesine tekrar tekrar basarak), indirme bazen başarısız olur.
kol

2
Sadece bu çözümün belirli bir eşikten daha büyük boyutlu dosyalar için çalışmayacağını belirtmek istedim. örneğin krom için 2 MB. Bu boyut tarayıcıdan tarayıcıya değişir.
manojadams

3
Dosyayı yeni bir sekmede açmam gerektiğinden bu benim için çalışmıyor. Chrome'da bir PDF göstermek zorundayım, ancak URL araç çubuğunda kullanıcı dostu bir ad göstermem gerekiyor ve kullanıcı indirme simgesiyle indirmek istiyorsa, dosyaya aynı kullanıcı dostu adı koymam gerekiyor.
Adrian Paredes

1
Sadece eklemek için, bunun çalışması için aslında bir etiketi gövdeye monte etmenize gerek yok (şimdi Chrome'da denendi)
kod

52

Ben sadece Internet Explorer (en modern sürümleri, her neyse) desteği ile kabul edilen cevabı genişletmek ve jQuery kullanarak kodu düzenlemek istedim:

$(document).ready(function() {
    saveFile("Example.txt", "data:attachment/text", "Hello, world.");
});

function saveFile (name, type, data) {
    if (data !== null && navigator.msSaveBlob)
        return navigator.msSaveBlob(new Blob([data], { type: type }), name);
    var a = $("<a style='display: none;'/>");
    var url = window.URL.createObjectURL(new Blob([data], {type: type}));
    a.attr("href", url);
    a.attr("download", name);
    $("body").append(a);
    a[0].click();
    window.URL.revokeObjectURL(url);
    a.remove();
}

İşte bir örnek Fiddle . Godspeed .


Mükemmel çalıştı.
N8allan

1
Kabul edilen çözümü kullandım ama firefox'ta işe yaramadı! Hala nedenini bilmiyorum. Çözümünüz firefox'ta çalıştı. Teşekkürler.
elahehab

@elahehab Çözümlerim her zaman çalışır;)
Alexandru

27

Yukarıdaki çözümlerle aynı prensip. Ancak büyük dosyaların (> 40 MByte) rasgele konumlarda kesildiği Firefox 52.0 (32 bit) ile ilgili sorunlar yaşadım. RevokeObjectUrl () çağrısının yeniden programlanması bu sorunu giderir.

function saveFile(blob, filename) {
  if (window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, filename);
  } else {
    const a = document.createElement('a');
    document.body.appendChild(a);
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    setTimeout(() => {
      window.URL.revokeObjectURL(url);
      document.body.removeChild(a);
    }, 0)
  }
}

jsfiddle örneği


1
Ben bu setTimeout () kesmek MS Edge, dosya hiç indirmez nerede giderir bulundu. Ancak, yalnızca revokeObjectURL () çağrısının ertelenmesi gerekir.
Russell Phillips

Ben "if (window.navigator.msSaveOrOpenBlob)" benim için hile yaptığını buldum
Jacques Olivier

23

Geç kaldım, ama aynı problemi yaşadığım için çözümümü ekliyorum:

function newFile(data, fileName) {
    var json = JSON.stringify(data);
    //IE11 support
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        let blob = new Blob([json], {type: "application/json"});
        window.navigator.msSaveOrOpenBlob(blob, fileName);
    } else {// other browsers
        let file = new File([json], fileName, {type: "application/json"});
        let exportUrl = URL.createObjectURL(file);
        window.location.assign(exportUrl);
        URL.revokeObjectURL(exportUrl);
    }
}

5
Teşekkürler @ben. Bu iyi çalışıyor. Dom öğesi yok, tıklama etkinliği gibi tetiklemek gibi bir şey yok. Sadece uygun uzatma ile harika çalışıyor. Ancak verilen dosya adı dikkate alınmaz, "<myfileName> .csv" yerine "<object_url_id> .csv" indirilir
Ram Babu S

3
Firefox'ta çağrı revokeObjectURLsonrası iyi location.assignçalışır, ancak Chrome'da indirmeyi keser.
Fred

"Edge'in Dosya yapıcısını desteklemediğini" unutmayın. Ref. caniuse.com/#feat=fileapi
user1477388

Bu doğru cevap olmalı. DOM ağacında işe yaramaz nesneler yaratmanın bir anlamı yok
Luiz Felipe

Şimdi, Ocak '20'den beri
Luiz Felipe

6
saveFileOnUserDevice = function(file){ // content: blob, name: string
        if(navigator.msSaveBlob){ // For ie and Edge
            return navigator.msSaveBlob(file.content, file.name);
        }
        else{
            let link = document.createElement('a');
            link.href = window.URL.createObjectURL(file.content);
            link.download = file.name;
            document.body.appendChild(link);
            link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));
            link.remove();
            window.URL.revokeObjectURL(link.href);
        }
    }

içinde yeni bir pencere açmanın bir yolu var mı?
Enrique Altuna

link.click()Bir fare olayı göndermek yerine arayabileceğinizi düşünüyorum .
Fred

2

Çalışma örneğiBir url'deki kedi fotoğrafını "cat.jpg" olarak kaydetmek için indirme düğmesinin :

HTML:

<button onclick="downloadUrl('https://i.imgur.com/AD3MbBi.jpg', 'cat.jpg')">Download</button>

JavaScript:

function downloadUrl(url, filename) {
  let xhr = new XMLHttpRequest();
  xhr.open("GET", url, true);
  xhr.responseType = "blob";
  xhr.onload = function(e) {
    if (this.status == 200) {
      const blob = this.response;
      const a = document.createElement("a");
      document.body.appendChild(a);
      const blobUrl = window.URL.createObjectURL(blob);
      a.href = blobUrl;
      a.download = filename;
      a.click();
      setTimeout(() => {
        window.URL.revokeObjectURL(blobUrl);
        document.body.removeChild(a);
      }, 0);
    }
  };
  xhr.send();
}

1

window.location.assign benim için çalışmadı. iyi indirir, ancak Windows platformunda bir CSV dosyası için uzantı olmadan indirir. Aşağıdakiler benim için çalıştı.

    var blob = new Blob([csvString], { type: 'text/csv' });
    //window.location.assign(window.URL.createObjectURL(blob));
    var link = window.document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    // Construct filename dynamically and set to link.download
    link.download = link.href.split('/').pop() + '.' + extension; 
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

0

Bu benim çözümüm. Benim açımdan, atlayamazsın <a>.

function export2json() {
  const data = {
    a: '111',
    b: '222',
    c: '333'
  };
  const a = document.createElement("a");
  a.href = URL.createObjectURL(
    new Blob([JSON.stringify(data, null, 2)], {
      type: "application/json"
    })
  );
  a.setAttribute("download", "data.json");
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}
<button onclick="export2json()">Export data to json file</button>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.