it-swarm.com.de

Erstellen Sie eine Datei im Speicher, die der Benutzer herunterladen kann, nicht über den Server

Gibt es eine Möglichkeit, eine Textdatei auf der Clientseite zu erstellen und den Benutzer aufzufordern, die Datei ohne Interaktion mit dem Server herunterzuladen? Ich weiß, dass ich nicht direkt auf den Computer schreiben kann (Sicherheit und alle), aber Kann ich sie erstellen und zum Speichern auffordern?

696
Joseph Silber

Sie können Daten-URIs verwenden. Die Browser-Unterstützung ist unterschiedlich. siehe Wikipedia . Beispiel:

<a href="data:application/octet-stream;charset=utf-16le;base64,//5mAG8AbwAgAGIAYQByAAoA">text file</a>

Der Octet-Stream soll eine Download-Aufforderung erzwingen. Andernfalls wird es wahrscheinlich im Browser geöffnet.

Für CSV können Sie Folgendes verwenden:

<a href="data:application/octet-stream,field1%2Cfield2%0Afoo%2Cbar%0Agoo%2Cgai%0A">CSV Octet</a>

Probieren Sie die jsFiddle Demo aus.

381

Einfache Lösung für HTML5-fähige Browser ...

function download(filename, text) {
  var element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}
form * {
  display: block;
  margin: 10px;
}
<form onsubmit="download(this['name'].value, this['text'].value)">
  <input type="text" name="name" value="test.txt">
  <textarea name="text"></textarea>
  <input type="submit" value="Download">
</form>

Verwendungszweck

download('test.txt', 'Hello world!');
606
Matěj Pokorný

Das obige Beispiel funktioniert in Chrome und IE gut, schlägt jedoch in Firefox fehl .. Ziehen Sie in Betracht, einen Anker an den Körper anzuhängen und ihn nach dem Klicken zu entfernen.

var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob(['Test,Text'], {type: 'text/csv'}));
a.download = 'test.csv';

// Append anchor to body.
document.body.appendChild(a);
a.click();

// Remove anchor from body
document.body.removeChild(a);
169
naren

Alle oben genannten Lösungen funktionierten nicht in allen Browsern. Folgendes funktioniert endlich auf IE 10+, Firefox und Chrome (und ohne jQuery oder eine andere Bibliothek):

save: function(filename, data) {
    var blob = new Blob([data], {type: 'text/csv'});
    if(window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveBlob(blob, filename);
    }
    else{
        var elem = window.document.createElement('a');
        elem.href = window.URL.createObjectURL(blob);
        elem.download = filename;        
        document.body.appendChild(elem);
        elem.click();        
        document.body.removeChild(elem);
    }
}

Beachten Sie, dass Sie abhängig von Ihrer Situation möglicherweise auch URL.revokeObjectURL aufrufen möchten, nachdem Sie elem entfernt haben. Laut den Dokumenten für URL.createObjectURL :

Bei jedem Aufruf von createObjectURL () wird eine neue Objekt-URL erstellt, auch wenn Sie bereits eine für dasselbe Objekt erstellt haben. Jeder von diesen muss durch Aufruf von URL.revokeObjectURL () freigegeben werden, wenn Sie sie nicht mehr benötigen. Browser geben diese automatisch frei, wenn das Dokument entladen wird. Für eine optimale Leistung und Speichernutzung sollten Sie dies jedoch tun, wenn sichere Zeiten vorliegen, in denen Sie sie explizit entladen können.

162
Ludovic Feltz

Ich benutze gerne FileSaver.js . Seine Kompatibilität ist ziemlich gut (IE10 + und alles andere) und es ist sehr einfach zu bedienen:

var blob = new Blob(["some text"], {
    type: "text/plain;charset=utf-8;",
});
saveAs(blob, "thing.txt");
106

Die folgende Methode funktioniert in IE11 +, Firefox 25+ und Chrome 30+:

<a id="export" class="myButton" download="" href="#">export</a>
<script>
    function createDownloadLink(anchorSelector, str, fileName){
        if(window.navigator.msSaveOrOpenBlob) {
            var fileData = [str];
            blobObject = new Blob(fileData);
            $(anchorSelector).click(function(){
                window.navigator.msSaveOrOpenBlob(blobObject, fileName);
            });
        } else {
            var url = "data:text/plain;charset=utf-8," + encodeURIComponent(str);
            $(anchorSelector).attr("download", fileName);               
            $(anchorSelector).attr("href", url);
        }
    }

    $(function () {
        var str = "hi,file";
        createDownloadLink("#export",str,"file.txt");
    });

</script>

Sehen Sie dies in Aktion: http://jsfiddle.net/Kg7eA/

Firefox und Chrome unterstützen die Daten-URI für die Navigation, sodass wir Dateien erstellen können, indem Sie zu einer Daten-URI navigieren, während IE sie aus Sicherheitsgründen nicht unterstützt. 

Auf der anderen Seite hat IE eine API zum Speichern eines Blobs, mit dem Dateien erstellt und heruntergeladen werden können.

22
dinesh ygv

Diese Lösung wird direkt aus dem Giddub-Repository von tiddlywiki (tiddlywiki.com) extrahiert. Ich habe Tiddlywiki in fast allen Browsern verwendet und es funktioniert wie ein Zauber:

function(filename,text){
    // Set up the link
    var link = document.createElement("a");
    link.setAttribute("target","_blank");
    if(Blob !== undefined) {
        var blob = new Blob([text], {type: "text/plain"});
        link.setAttribute("href", URL.createObjectURL(blob));
    } else {
        link.setAttribute("href","data:text/plain," + encodeURIComponent(text));
    }
    link.setAttribute("download",filename);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

Github Repo: Speichermodul herunterladen

11
Danielo515

Lösung, die unter IE10 funktioniert: (Ich habe eine CSV-Datei benötigt, aber es reicht aus, Typ und Dateinamen in TXT zu ändern.)

var csvContent=data; //here we load our csv data 
var blob = new Blob([csvContent],{
    type: "text/csv;charset=utf-8;"
});

navigator.msSaveBlob(blob, "filename.csv")
10
Dzarek

Wenn Sie nur einen String konvertieren möchten, der zum Download zur Verfügung steht, können Sie dies mit jQuery versuchen.

$('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data));
9
Rick
var element = document.createElement('a');
element.setAttribute('href', 'data:text/text;charset=utf-8,' +      encodeURI(data));
element.setAttribute('download', "fileName.txt");
element.click();
7
MANVENDRA LODHI

Wie bereits erwähnt, ist filesaver ein großartiges Paket für die Arbeit mit Dateien auf der Clientseite. Aber mit großen Dateien ist das nicht gut. StreamSaver.js ist eine alternative Lösung (auf die FileServer.js verweist), die große Dateien verarbeiten kann:

const fileStream = streamSaver.createWriteStream('filename.txt', size);
const writer = fileStream.getWriter();
for(var i = 0; i < 100; i++){
    var uint8array = new TextEncoder("utf-8").encode("Plain Text");
    writer.write(uint8array);
}
writer.close()
6
مصطفی

Seit April 2014 sind FileSytem-APIs in W3C möglicherweise nicht standardisiert. Jeder, der die Lösung mit Blob betrachtet, sollte mit Vorsicht vorgehen, schätze ich.

HTML5 rockt den Kopf hoch

W3C-Mailingliste in der FileSytem-API

5
pravin

Basierend auf der Antwort von @Rick, die wirklich hilfreich war.

Sie müssen den String data scape, wenn Sie ihn folgendermaßen teilen möchten:

$('a.download').attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(data));

` Leider kann ich die Antwort von @ Rick aufgrund meines derzeitigen niedrigen Rufs in StackOverflow nicht kommentieren.

Ein Bearbeitungsvorschlag wurde geteilt und abgelehnt.

5
atfornes

Sie können sogar eine bessere als nur URIs verwenden. Mit Chrome können Sie auch den Namen der Datei vorschlagen, wie in diesem Blogbeitrag zum Benennen eines Downloads bei Verwendung von URIs .

3
owencm

Das Paket js-file-download von github.com/kennethjiang/js-file-download behandelt Edge-Fälle für die Browserunterstützung:

Quelltext anzeigen um zu sehen, wie es die auf dieser Seite erwähnten Techniken verwendet.

Installation

yarn add js-file-download
npm install --save js-file-download

Verwendungszweck

import fileDownload from 'js-file-download'

// fileDownload(data, filename, mime)
// mime is optional

fileDownload(data, 'filename.csv', 'text/csv')
0
Beau Smith

Wir können die URL API verwenden, insbesondere RL.createObjectURL () , und die Blob API, um so ziemlich alles zu kodieren und herunterzuladen.

document.body.innerHTML += 
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify("HELLO WORLD", null, 2)]))}"> Click me</a>`
download.click()
download.outerHTML = ""

Bonus! Laden Sie alle zyklischen Objekte herunter, vermeiden Sie die Fehler:

TypeError: Zyklischer Objektwert (Firefox) TypeError: Konvertieren

kreisförmige Struktur in JSON (Chrome und Opera) TypeError: Circular

referenz im Wertargument nicht unterstützt (Edge)

Verwenden Sie https://github.com/douglascrockford/JSON-js/blob/master/cycle.js

/* JSON.decycle */
if(typeof JSON.decycle!=="function"){JSON.decycle=function decycle(object,replacer){"use strict";var objects=new WeakMap();return(function derez(value,path){var old_path;var nu;if(replacer!==undefined){value=replacer(value)}
if(typeof value==="object"&&value!==null&&!(value instanceof Boolean)&&!(value instanceof Date)&&!(value instanceof Number)&&!(value instanceof RegExp)&&!(value instanceof String)){old_path=objects.get(value);if(old_path!==undefined){return{$ref:old_path}}
objects.set(value,path);if(Array.isArray(value)){nu=[];value.forEach(function(element,i){nu[i]=derez(element,path+"["+i+"]")})}else{nu={};Object.keys(value).forEach(function(name){nu[name]=derez(value[name],path+"["+JSON.stringify(name)+"]")})}
return nu}
return value}(object,"$"))}}


document.body.innerHTML += 
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify(JSON.decycle(document), null, 2)]))}"></a>`
download.click()
0
NVRM

Für mich funktionierte dies perfekt, wobei derselbe Dateiname und die gleiche Erweiterung heruntergeladen wurden

<a href={"data:application/octet-stream;charset=utf-16le;base64," + file64 } download={title} >{title}</a>

'title' ist der Dateiname mit der Erweiterung d. h., sample.pdf, waterfall.jpg usw.

'file64' ist der base64-Inhalt, der ungefähr so ​​aussieht, d. h. Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO

0
abdul

Diese untenstehende Funktion hat funktioniert.

 private createDownloadableCsvFile(fileName, content) {
   let link = document.createElement("a");
   link.download = fileName;
   link.href = `data:application/octet-stream,${content}`;
   return link;
 }
0
bountyhunter