Jak utworzyć plik w pamięci do pobrania przez użytkownika, ale nie przez serwer?

Czy jest jakiś sposób, aby utworzyć plik tekstowy po stronie klienta i poprosić użytkownika, aby go pobrać, bez żadnej interakcji z serwerem? Wiem, że nie mogę pisać bezpośrednio na ich komputerze(Bezpieczeństwo i w ogóle), ale czy mogę utworzyć i poprosić ich o zapisanie?

Author: Matko, 2010-09-08

21 answers

Możesz użyć Uri danych. Obsługa przeglądarek jest różna; Zobacz Wikipedia . Przykład:

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

Strumień oktetu ma wymusić monit o pobranie. W przeciwnym razie prawdopodobnie otworzy się w przeglądarce.

Do CSV możesz użyć:

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

Spróbuj jsfiddle demo .

 449
Author: Matthew Flaschen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-08 08:10:02

Proste rozwiązanie dla przeglądarek gotowych do HTML5...

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>

Użycie

download('test.txt', 'Hello world!');
 786
Author: Matěj Pokorný,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-30 20:08:51

Wszystkie powyższe rozwiązania nie działały we wszystkich przeglądarkach. Oto, co w końcu działa na IE 10+, Firefox i Chrome (i Bez jQuery lub jakiejkolwiek innej biblioteki):

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

Zauważ, że w zależności od twojej sytuacji możesz również zadzwonić do URL .revokeObjectURL po usunięciu elem. Zgodnie z docs dla URL.createObjectURL :

Za każdym razem, gdy wywołujesz createObjectURL (), tworzony jest nowy adres URL obiektu, nawet jeśli utworzyłeś go już dla tego samego obiekt. Każdy z nich musi być zwolniony przez wywołanie URL.revokeObjectURL (), gdy nie są już potrzebne. Przeglądarki zwalniają je automatycznie po rozładowaniu dokumentu; jednak dla optymalnej wydajności i wykorzystania pamięci, jeśli są bezpieczne czasy, kiedy można je wyraźnie rozładować, należy to zrobić.

 259
Author: Ludovic Feltz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-12 15:20:01

Wszystkie powyższe przykłady działają dobrze w chrome i IE, ale nie w Firefoksie. Rozważ dodanie kotwicy do ciała i usunięcie jej po kliknięciu.

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);
 190
Author: naren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-18 16:11:24

Z przyjemnością korzystam FileSaver.js . Jego kompatybilność jest całkiem dobra (IE10+ i wszystko inne) i jest bardzo prosta w użyciu:

var blob = new Blob(["some text"], {
    type: "text/plain;charset=utf-8;",
});
saveAs(blob, "thing.txt");
 124
Author: Daniel Buckmaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-08 23:05:25

Następująca metoda działa w IE11+, Firefox 25 + i 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>

Zobacz to w akcji: http://jsfiddle.net/Kg7eA/

Firefox i Chrome obsługują Dane URI do nawigacji, co pozwala nam tworzyć pliki, przechodząc do danych URI, podczas gdy IE nie obsługuje go ze względów bezpieczeństwa.

Z drugiej strony, IE posiada API do zapisywania obiektów blob, które można wykorzystać do tworzenia i pobierania plików.

 21
Author: dinesh ygv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-27 06:55:52

To rozwiązanie jest pobierane bezpośrednio z tiddlywiki (tiddlywiki.com) repozytorium github. Używałem tiddlywiki w prawie wszystkich przeglądarkach i działa jak urok:

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: pobierz Moduł wygaszacza

 13
Author: Danielo515,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 18:52:36

Pakiet js-file-download z github.com/kennethjiang/js-file-download obsługuje obudowy edge dla obsługi przeglądarki:

Zobacz źródło , aby zobaczyć, jak wykorzystuje techniki wymienione na tej stronie.

Instalacja

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

Użycie

import fileDownload from 'js-file-download'

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

fileDownload(data, 'filename.csv', 'text/csv')
 13
Author: Beau Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-04 23:17:34

Rozwiązanie działające na IE10: (Potrzebowałem pliku csv, ale wystarczy zmienić typ i nazwę pliku na txt)

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")
 11
Author: Dzarek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-27 09:10:59

Jeśli chcesz przekonwertować ciąg znaków, aby był dostępny do pobrania, możesz spróbować tego za pomocą jQuery.

$('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data));
 11
Author: Rick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-16 16:41:32

Możemy użyć URL api, w szczególności URL.createObjectURL () i API Blob do kodowania i pobierania praktycznie wszystkiego.

Jeśli pobieranie jest małe, to działa dobrze:

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 = ""

Jeśli pobieranie jest ogromne, zamiast używać DOM, lepszym sposobem jest utworzenie elementu łącza z parametrami pobierania i uruchomienie kliknięcia.

Zauważ, że element łącza nie jest dołączany do dokumentu, ale kliknięcie i tak działa! Jest to możliwe, aby utworzyć pobieranie wielu setek Mo w ten sposób.

const stack = {
 some: "stuffs",
 alot: "of them!"
}

BUTTONDOWNLOAD.onclick = (function(){
  let j = document.createElement("a")
  j.download = "stack_"+Date.now()+".json"
  j.href = URL.createObjectURL(new Blob([JSON.stringify(stack, null, 2)]))
  j.click()
})
<button id="BUTTONDOWNLOAD">DOWNLOAD!</button>

Bonus! Pobierz dowolne obiekty cykliczne , unikaj błędów:

TypeError: cyclic object value (Firefox) TypeError: Converter

Circular structure to JSON (Chrome and Opera) TypeError: Circular

Odniesienie do argumentu wartości nie jest obsługiwane (Edge)

Za pomocą https://github.com/douglascrockford/JSON-js/blob/master/cycle.js

W tym przykładzie pobieramy obiekt document jako json.

/* 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()
 9
Author: NVRM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-24 16:13:09

Jak wspomniano wcześniej, filesaver jest świetnym pakietem do pracy z plikami po stronie klienta. Ale nie jest dobrze z dużymi plikami. StreamSaver.js jest alternatywnym rozwiązaniem (wskazywanym w serwerze plików.js), które mogą obsługiwać duże pliki:

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()
 8
Author: Mostafa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-16 20:42:42
var element = document.createElement('a');
element.setAttribute('href', 'data:text/text;charset=utf-8,' +      encodeURI(data));
element.setAttribute('download', "fileName.txt");
element.click();
 7
Author: MANVENDRA LODHI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-09 11:55:37

Od kwietnia 2014 r. API plików mogą nie być standaryzowane w W3C. każdy, kto patrzy na rozwiązanie z blobem, powinien zachować ostrożność.

HTML5 rocks heads up

Lista dyskusyjna W3C na FileSytem API

 5
Author: pravin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-20 15:47:54

Na podstawie odpowiedzi @ Rick, która była bardzo pomocna.

Musisz scape the string data jeśli chcesz podzielić się nim w ten sposób:

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

` Sorry I can not comment on @ Rick ' s answer due to my current low reputation in StackOverflow.

An sugestia edycji {[10] } została udostępniona i odrzucona.

 5
Author: atfornes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 14:59:01

Ta funkcja poniżej zadziałała.

 private createDownloadableCsvFile(fileName, content) {
   let link = document.createElement("a");
   link.download = fileName;
   link.href = `data:application/octet-stream,${content}`;
   return link;
 }
 2
Author: giapnh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-25 02:29:59

Następująca metoda działa w IE10+, Edge, Opera, FF i Chrome:

const saveDownloadedData = (fileName, data) => {
    if(~navigator.userAgent.indexOf('MSIE') || ~navigator.appVersion.indexOf('Trident/')) { /* IE9-11 */
        const blob = new Blob([data], { type: 'text/csv;charset=utf-8;' });
        navigator.msSaveBlob(blob, fileName);
    } else {
        const link = document.createElement('a')
        link.setAttribute('target', '_blank');
        if(Blob !== undefined) {
            const blob = new Blob([data], { type: 'text/plain' });
            link.setAttribute('href', URL.createObjectURL(blob));
        } else {
            link.setAttribute('href', 'data:text/plain,' + encodeURIComponent(data));
        }

        ~window.navigator.userAgent.indexOf('Edge')
            && (fileName = fileName.replace(/[&\/\\#,+$~%.'':*?<>{}]/g, '_')); /* Edge */

        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }
}

Więc wystarczy wywołać funkcję:

saveDownloadedData('test.txt', 'Lorem ipsum');
 1
Author: Denys Rusov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-14 02:17:36

To działa dla mnie (Chrome 86):

function download(content, mimeType, filename){
  var a = document.createElement('a')
  var blob = new Blob([content], {type: mimeType})
  var url = URL.createObjectURL(blob)
  a.setAttribute('href', url)
  a.setAttribute('download', filename)
  a.click()
}

Tutaj można zobaczyć Skrzypce: https://jsfiddle.net/Stelios2020/ukmf5304/6/

 1
Author: Στυλιανός Παρασυράκης,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-19 08:57:00

Dla mnie to działało idealnie, z tą samą nazwą pliku i rozszerzeniem pobieranym

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

'title' to nazwa pliku z rozszerzeniem tj., sample.pdf, waterfall.jpg, itd..

'file64' jest zawartością base64 coś w tym stylu, tzn. Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO

 0
Author: abdul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-17 10:13:23

Użyłbym znacznika <a></a>, a następnie ustawić href='path'. Następnie umieść obraz pomiędzy elementami <a>, abym mógł go zobaczyć. Jeśli chcesz, możesz utworzyć funkcję, która zmieni href tak, że nie będzie to tylko to samo łącze, ale będzie dynamiczne.

Podaj tag <a> oraz id, jeśli chcesz uzyskać do niego dostęp za pomocą javascript.

Począwszy od wersji HTML:

<a href="mp3/tupac_shakur-how-do-you-want-it.mp3" download id="mp3Anchor">
     <img src="some image that you want" alt="some description" width="100px" height="100px" />
</a>

Teraz z JavaScript:

*Create a small json file*;

const array = [
     "mp3/tupac_shakur-how-do-you-want-it.mp3",
     "mp3/spice_one-born-to-die.mp3",
     "mp3/captain_planet_theme_song.mp3",
     "mp3/tenchu-intro.mp3",
     "mp3/resident_evil_nemesis-intro-theme.mp3"
];

//load this function on window
window.addEventListener("load", downloadList);

//now create a function that will change the content of the href with every click
function downloadList() {
     var changeHref=document.getElementById("mp3Anchor");

     var j = -1;

     changeHref.addEventListener("click", ()=> {

           if(j < array.length-1) {
               j +=1;
               changeHref.href=""+array[j];
          }
           else {
               alert("No more content to download");
          }
}
 0
Author: darrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-14 22:12:47

Jeśli plik zawiera dane tekstowe, techniką, której używam, jest umieszczenie tekstu w elemencie textarea i wybranie go przez użytkownika (kliknij w textarea, a następnie ctrl-A), a następnie skopiowanie i wklejenie do edytora tekstu.

 -24
Author: HBP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-08 06:51:27