Veri kullanırken önerilen bir dosya adı belirtmenin bir yolu var mı: URI?


225

Örneğin bağlantıyı takip ediyorsanız:

data:application/octet-stream;base64,SGVsbG8=

Tarayıcı, köprünün kendisinde base64 olarak tutulan verilerden oluşan bir dosyayı indirmenizi ister. İşaretlemede varsayılan bir ad önermenin bir yolu var mı? Değilse, bir JavaScript çözümü var mı?


belki bu sorunla ilgisiz ama bu bir sunucu veya eski tarayıcı engel değilse blob & URL.createObjectURL kullanmanızı öneririm
Endless

3
Bazı tarayıcılar, data:application/pdf;name=document.pdf;base64,BASE64_DATA_ENCODED
mediatype'ın

Firefox pdf.js ile ilgili bir sorunum vardı, bu veri uri'den bir dosya adı çıkaramazsa bazı durumlarda askıda kalıyor. bkz. stackoverflow.com/questions/45585921/…
Bernhard

@mems Hangi tarayıcılar "name" parametresini destekliyor? Beni referans belgelerine yönlendirebilir misiniz? (google-fu'm başarısız oldu).
TheAddonDepot

@DimuDesigns O zaman en azından Firefox. Artık durum böyle değil. MIME Content-Type (! = Content-Disposition) "name" parametresiyle (RFC'de değil mi?)
İlgilidir

Yanıtlar:


158

Şu özelliği kullanın download:

<a download='FileName' href='your_url'>

Html5-demos.appspot.com / ... adresinde canlı örnek .

Şu anda Chrome, Firefox, Edge, Opera ve masaüstü Safari'de çalışıyor ancak iOS Safari veya IE11'de çalışmıyor.


3
@BioDesign: Verilerle bile çalışır: kromdaki URI'ler. Bkz: jsfiddle.net/pYpqW
Senseful

6
ama bunu yapamazsın window.location.replace. örneğin bir veri oluşturmak istiyorsanız: uri veya tarafından oluşturulan bir veri window.URL.createObjectURLve bunu dosya olarak indirmek için bir <a> oluşturmanız ve tıklamanız gerekir: jsfiddle.net/flyingsheep/wpQtH (hayır, $(...).click()çalışmıyor)
uçan koyun

1
Sadece tüm tarayıcılar Chrome
gibiyse

6
@flyingsheep $('<a href="data:text/plain,Test" download="test.txt">')[0].click()burada iyi çalışıyor gibi görünüyor (Chrome 23) (not: jQuery'nin yöntemini değil , yerel clickyöntemi kullandım ). Demo: jsfiddle.net/2zsRW
Rob W

1
@flyingsheep, Firefox'ta aynı köken politikasını uyguluyor gibi görünüyor. "Firefox 20'de bu özellik yalnızca aynı kökene sahip kaynaklara bağlantılar için onurlandırıldı." developer.mozilla.org/tr-TR/docs/Web/HTML/Element/a Testlerimde Chrome'un bu sınırlaması yok.
William Denniss

62

Chrome bunu bugünlerde çok basit hale getiriyor:

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}

Tüm bu cevapların ne hakkında konuştuğunu bilmiyorum, Chrome 30'da ilk denemede çalıştı.
Michael J. Calkins

2
Şimdi öyle ama her zaman bu kadar kolay olmadı. Bu cevapların çoğu yıllar öncesindendir. Ayrıca diğer tarayıcılarda da çalışırlar.
Holf

7
Tarayıcı uyumluluğunun tam listesi için http://caniuse.com/#feat=download adresine bakın .
tixastronauta

2
@tixastronauta: Bu sayfadaki bilgilere rağmen, firefox 44'ümde çalışmıyor. Chrome'da iyi çalışıyor. 48
Luis A. Florit

Merhaba @Holf da dosya türü veya uzantısı veya dosya adı olarak spceficy kadar basit eklemek için bir yolu var mı?
Fraccier

51

Yalnızca HTML: şu downloadözelliği kullanın :

<a download="logo.gif" href="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">Download transparent png</a>


Yalnızca Javascript: Herhangi bir veri URI'sini şu kodla kaydedebilirsiniz:

function saveAs(uri, filename) {
  var link = document.createElement('a');
  if (typeof link.download === 'string') {
    link.href = uri;
    link.download = filename;

    //Firefox requires the link to be in the body
    document.body.appendChild(link);
    
    //simulate click
    link.click();

    //remove the link when done
    document.body.removeChild(link);
  } else {
    window.open(uri);
  }
}

var file = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
saveAs(file, 'logo.gif');

Chrome, Firefox ve Edge 13+ belirtilen dosya adını kullanır.

IE11, Edge 12 ve Safari 9 ( özniteliği desteklemeyendownload ) dosyayı varsayılan adlarıyla indirir veya desteklenen bir dosya türündeyse yeni bir sekmede görüntüler: resimler, videolar, ses dosyaları ,…


Her iki demo da Chrome 38'de benim için iyi çalışıyor (ancak Chrome 14+'da çalışması gerekir)
fregante

Daha eksiksiz bir çözüm downloadjsiçin npm'de
fregante

Benim için çalışıyor ancak bundan sonra tarayıcı sayfası yenileniyor. Bunu nasıl önleyeceğini merak ediyor musun?

1
Dosya boyutu için krom Çalışmaz> 2MB krom tarafından kısıtlama nedeniyle stackoverflow.com/questions/695151/...
Pranav Singh

Limit data:, sorunun bahsettiği URI'ye aittir . Bu cevap aynı zamanda Blobs ile ve başka bir
URI'ye

40

RFC 2397'ye göre hayır yok.

Öğenin kullanabileceğiniz herhangi bir özelliği de görünmüyor <a>.

Bununla birlikte, HTML5, daha sonra yazma desteği evrensel olmasa da download, <a>öğe üzerinde niteliği tanıttı (örneğin, MSIE desteği yok)


9
ikinci cümle yazıldığı sırada doğruydu, ama artık değil . şu an itibariyle, henüz geniş çapta uygulanmadı.
uçan koyun

daha fazla bilgi için bu yoruma bakın :)
uçan koyun

@flyingsheep, O olduğu yaygın uygulamıştır.
Pacerier

1
bu yorumu yazdığımda 3 yıl önce değildi
uçan koyun

Dosya çok uzunsa indirme başarısız olur
deFreitas

21

Netwerk / protokol / veri / nsDataHandler.cpp firefox kaynaklarında biraz baktım

veri işleyici yalnızca içeriği / türü ve karakter kümesini ayrıştırır ve dizede "; base64" olup olmadığına bakar

rfc dosya adı belirtmez ve en azından firefox bunun için dosya adı işlemez, kod rasgele bir ad artı ".part" oluşturur

Ayrıca firefox günlüğünü de kontrol ettim

[b2e140]: DOCSHELL 6e5ae00 InternalLoad data:application/octet-stream;base64,SGVsbG8=
[b2e140]: Found extension '' (filename is '', handling attachment: 0)
[b2e140]: HelperAppService::DoContent: mime 'application/octet-stream', extension ''
[b2e140]: Getting mimeinfo from type 'application/octet-stream' ext ''
[b2e140]: Extension lookup on '' found: 0x0
[b2e140]: Ext. lookup for '' found 0x0
[b2e140]: OS gave back 0x43609a0 - found: 0
[b2e140]: Searched extras (by type), rv 0x80004005
[b2e140]: MIME Info Summary: Type 'application/octet-stream', Primary Ext ''
[b2e140]: Type/Ext lookup found 0x43609a0

kaynaklarına bakmak istiyorsanız ilginç dosyalar:

data uri handler: netwerk/protocol/data/nsDataHandler.cpp
where mozilla decides the filename: uriloader/exthandler/nsExternalHelperAppService.cpp
InternalLoad string in the log: docshell/base/nsDocShell.cpp

Şimdilik bir çözüm aramayı bırakabileceğinizi düşünüyorum, çünkü hiç şüphesiz :)

html5'in bu konuda fark ettiği gibi download, firefox 20 üzerinde de çalışıyor http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-download


3
Güzel! Her ne kadar Firefox'un var olanla ilgili nihai otorite olduğu konusunda hemfikir değilim. :)
Gleno

14

Aşağıdaki Javascript snippet'i, bağlantıların yeni 'indir' özelliğini kullanarak ve bir tıklamayı simüle ederek Chrome'da çalışır.

function downloadWithName(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  link.click();
}

Ve aşağıdaki örnek bunun kullanımını göstermektedir:

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")

1
Bu Firefox'ta çalışmıyor, aşağıya Fx uyumluluğu ile genişletilmiş bir cevap ekledim.
fregante

12

Hayır.

Tüm amaç, bir dosya değil, bir veri akışı olmasıdır. Veri kaynağı, onu bir dosya olarak işleyen kullanıcı aracısı hakkında hiçbir bilgiye sahip olmamalıdır ...


6
Amacı, dahili veri data:bloğunu protokol tabanlı bir kaynaktan okumak zorunda kalmadan URL biçimine dönüştürmektir . @ Silex'in cevabındaki bağlantı, henüz uygulanmamış olsa bile, tercih edilen bir ismi yazmak için önerme yeteneğinin yararlı olduğunu göstermektedir.
Alnitak

1
@Alnitak: Yararlı mı? Kesinlikle. Teknik olarak uygun mu? Hala ikna olmadım. :)
Orbit'te Hafiflik Yarışları

3
@Tomalak verileri yüklemek ve kaydetmek arasındaki farkı göz önünde bulundurun - tıpkı bir blob bir veri içinde satır içi olarak kodlandığı için: URL, onu kaydetmek için tercih edilen bir isme sahip olmaması gerektiği anlamına gelmez.
Alnitak

4
Ama onun "bütün amacı" hakkındaki çizginiz yanlış. data:(küçük) satır içi içeriğin ayrı bir HTTP isteği olmadan resim etiketleri gibi şeyler tarafından kullanılabilmesi için bir araya getirilmiş URL biçiminde görünmesine izin vermek için özel olarak icat edildi . HTML, bir img srcözelliğin içeriğinin bir URL olması gerektiğini, bu nedenle RFC 2397'nin oluşturduğu şey olduğunu söylüyor. "Veri kaynağı" yok.
Alnitak

6
@Alnitak: Kesinlikle. Veri kaynağı yok. Bağlam yok. URI olduğunu verileri.
Yörüngedeki Hafiflik Yarışları

9

bağlantı elemanına bir indirme özelliği ekleyebilirsiniz.

örneklem:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>

5

Şu bağlantıya bakın: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html

Alıntı:

Hatta şu şekilde çalışır (olduğu gibi, soruna neden olmaz); base64 şu şekilde
(en azından Opera'da):

veriler: metin / düz; charset = UTF-8; başlıklar = İçerik-Disposition% 3A% 20attachment% 3B% 20filename% 3D% 22with% 20spaces.txt% 22% 0D% 0AContent dil% 3A% 20en; base64,4oiaDQo% 3 boyutlu

Ayrıca tartışmanın geri kalan mesajlarında bazı bilgiler var.


ne yazık ki bu indirmiyor.
James Khoury

7
bu tartışma, veri URI biçimine önerilen bir uzantı içindir - uygulanmadı.
Alnitak

Uygulanmış olsun veya olmasın, keyfi parametreler için mevcut destekle bu harika olurdu.
Dan Lugg

5

Servis çalışanlarını kullanarak , bu en doğru şekilde mümkün.

  1. Sahte bir URL oluşturun. Örneğin /saveAs/myPrettyName.jpg
  2. URL'yi <a href, <img srcwindow.open (url) dizininde, kesinlikle "gerçek" bir URL ile yapılabilecek her şeyi kullanın .
  3. İşçinin içinde, getirme olayını yakalayın ve doğru verilerle yanıt verin.

Tarayıcı, kullanıcı dosyayı yeni bir sekmede açıp oraya kaydetmeye çalışsa bile myPrettyName.jpg dosyasını önerecektir. Dosya sunucudan gelmiş gibi olur.

// In the service worker
self.addEventListener( 'fetch', function(e)
{
    if( e.request.url.startsWith( '/blobUri/' ) )
    {
        // Logic to select correct dataUri, and return it as a Response
        e.respondWith( dataURLAsRequest );
    }
});

1
İlginç! Destek şimdilik şimdilik sığ görünüyor: caniuse.com/#feat=serviceworkers
tuomassalo

Bir dosyaya başka bir doğrudan URL ile "yanıt vermenin" herhangi bir yolu var mı?
Iulian Onofrei

4

Google Code'da benim için çalışan küçük bir geçici çözüm betiği var:

http://code.google.com/p/download-data-uri/

İçindeki verilerle bir form ekler, gönderir ve sonra formu tekrar kaldırır. Hacky, ama bu işi benim için yaptı. JQuery gerektirir.

Bu iş parçacığı Google'da Google Kod sayfasından önce gösterildi ve bağlantıyı burada da eklemenin yararlı olacağını düşündüm.


İlginç bir komut dosyası ama sunucu yanıt ans geri göndermek için doğru gerektirir mi? jsfiddle.net/hZySf
James Khoury

Dosya nereden oluşturulduğundan emin değilim ... bu dosya base64 kodlamasında saklanıyor mu? (Base64'e fazla aşina değilim)
sokak lambası

@streetlight: "Dosya" (yani veriler) Javascript tarafından oluşturulur. Bu projenin bağlamı (ve muhtemelen en çok burada), istediğiniz verileri bir JS değişkenine almanın bir yoluna sahip olduğunuzu varsayar. Aradaki fark, kullanıcıya bir data:...URI aracılığıyla sunmak yerine , bu komut dosyasının sunucuya POST yapmak için bir form oluşturmasıdır. Ve sonra sunucu muhtemelen bir HTTP "indirme" yanıtı olarak geri yansıtır (yani dosya adını belirten uygun bir Content-Disposition üstbilgisi ile).
Andrzej Doyle

4

Holf'un sürümüne dayanan bir jQuery sürümü ve Chrome ve Firefox ile çalışıyor, ancak sürümü yalnızca Chrome ile çalışıyor gibi görünüyor. Bunu yapmak için vücuda bir şeyler eklemek biraz garip ama eğer birisi daha iyi bir seçeneğe sahipse, bunun için ben varım.

var exportFileName = "export-" + filename;
$('<a></a>', {
    "download": exportFileName,
    "href": "data:," + JSON.stringify(exportData, null,5),
    "id": "exportDataID"
}).appendTo("body")[0].click().remove();

1
JQuery 1.11 .remove () nedeniyle bir istisna alıyorum. Ben $().appendTo()bir değişken atayarak sonra çağırarak bu varvariable.click(); variable.remove()
p0lar_bear

@ p0lar_bear, bu istisnayı herhangi bir jQuery ile elde etmelisiniz, çünkü [0]herhangi bir "jQuery öğesinden" elde etmek , temsil ettiği ilk DOM öğesini döndürmelidir.
drzaus

Aslında öğeyi eklemeniz / kaldırmanız gerekmez - stackoverflow.com/a/17311705/1037948
drzaus

3

Bu biraz saçma, ama daha önce de aynı durumdaydım. Dinamik olarak javascript bir metin dosyası oluşturmak ve veri-URI ile kodlayarak indirmek için sağlamak istedim.

Bu, küçük çaplı büyük kullanıcı müdahaleleriyle mümkündür . Bir bağlantı oluşturun <a href="data:...">right-click me and select "Save Link As..." and save as "example.txt"</a>. Dediğim gibi, bu yetersizdir, ancak profesyonel bir çözüme ihtiyacınız yoksa çalışır.

Bu, önce adı panoya kopyalamak için flaş kullanılarak daha az acı verici olabilir. Tabii ki Flash veya Java kullanmanıza izin verirseniz (şimdi daha az ve daha az tarayıcı desteği ile?), Muhtemelen bunu yapmanın başka bir yolunu bulabilirsiniz.


Bu bir çözüm değildir ve istenenleri karşılamamaktadır. Afedersiniz.
jcolebrand

7
Lol @ "küçük kullanıcı müdahalesi". Kullanıcının sizin için her şeyi yapmasını sağlamak "küçük kullanıcı müdahalesi" değildir.
Yörüngedeki Hafiflik Yarışları

Oluşturulan bağlantıyı tetiklemek için stackoverflow.com/questions/17311645/… ile birleştirin ve kullanıcı müdahalesine gerek yoktur. Diğer birçok yanıtta belirtildiği gibi bir ad önermek için HTML5 downloadniteliğini belirtebilirsiniz .
drzaus

Bu Safari için harika bir çözümdür. İndirme özelliğinin desteklenmediğini tespit etmek ve bağlantı metnini güncellemek için Modernizr kullanın!
littledynamo

2

Bu Firefox 43.0 (daha eski test edilmemiştir) ile çalışır:

dl.js:

function download() {
  var msg="Hello world!";
  var blob = new File([msg], "hello.bin", {"type": "application/octet-stream"});

  var a = document.createElement("a");
  a.href = URL.createObjectURL(blob);

  window.location.href=a;
}

dl.html

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8"/>
    <title>Test</title>
    <script type="text/javascript" src="dl.js"></script>
</head>

<body>
<button id="create" type="button" onclick="download();">Download</button>
</body>
</html>

Düğme tıklanırsa , indirmek için hello.bin adlı bir dosya sundu . Hile Blob yerine File kullanmaktır .

başvuru: https://developer.mozilla.org/de/docs/Web/API/File


0
var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
var sessionId ='\n';
var token = '\n';
var caseId = CaseIDNumber + '\n';
var url = casewebUrl+'\n';
var uri = sessionId + token + caseId + url;//data in file
var fileName = "file.i4cvf";// any file name with any extension
if (isIE)
    {
            var fileData = ['\ufeff' + uri];
            var blobObject = new Blob(fileData);
            window.navigator.msSaveOrOpenBlob(blobObject, fileName);
    }
    else //chrome
    {
        window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
         window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) {
            fs.root.getFile(fileName, { create: true }, function (fileEntry) { 
                fileEntry.createWriter(function (fileWriter) {
                    var fileData = ['\ufeff' + uri];
                    var blob = new Blob(fileData);
                    fileWriter.addEventListener("writeend", function () {
                        var fileUrl = fileEntry.toURL();
                        var link = document.createElement('a');
                        link.href = fileUrl;
                        link.download = fileName;
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                    }, false);
                    fileWriter.write(blob);
                }, function () { });
            }, function () { });
         }, function () { });
    }

1
pls cevabınıza daha ayrıntılı bir açıklama ekleyin - stackoverflow.com/help/how-to-answer
Sebastian Brosch

1
bu cevap çöp
Jonathan Taylor

-2

Aslında bunu Chrome ve FireFox'ta başarabilirsiniz.

Aşağıdaki URL'yi deneyin, kullanılan kodu indirir.

data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==
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.