Как создать файл в памяти для загрузки пользователем, но не через сервер?

Можно ли создать текстовый файл на стороне клиента и предложить пользователю загрузить его без какого-либо взаимодействия с сервером? Я знаю, что не могу писать прямо на свою машину (безопасность и все), но могу ли я создать и предложить им сохранить ее?

Ответ 1

Вы можете использовать URI данных. Поддержка браузера варьируется; см. Wikipedia. Пример:

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

Октетный поток - это принудительное приглашение загрузки. В противном случае он, вероятно, откроется в браузере.

Для CSV вы можете использовать:

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

Попробуйте демонстрацию jsFiddle.

Ответ 2

Простое решение для готовых браузеров 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>

Ответ 3

Все вышеупомянутые решения не работали во всех браузерах. Вот что, наконец, работает на IE 10+, Firefox и Chrome (и без jQuery или любой другой библиотеки):

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

Обратите внимание, что в зависимости от вашей ситуации вы также можете вызвать URL.revokeObjectURL после удаления elem. Согласно документам для URL.createObjectURL:

Каждый раз, когда вы вызываете createObjectURL(), создается новый URL-адрес объекта, даже если вы уже создали его для одного и того же объекта. Каждый из них должен быть освобожден, вызывая URL.revokeObjectURL(), когда они вам больше не нужны. Браузеры автоматически освободят их, когда документ будет выгружен; однако, для оптимальной производительности и использования памяти, если есть безопасные моменты, когда вы можете явно их выгружать, вы должны это сделать.

Ответ 4

Все вышеприведенное приложение отлично работает в chrome и IE, но не работает в Firefox. Пожалуйста, обратите внимание на добавление привязки к телу и удаление его после нажатия.

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

Ответ 5

Я с удовольствием использую FileSaver.js. Совместимость неплохая (IE10 + и все остальное), и она очень проста в использовании:

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

Ответ 6

Следующий метод работает в IE11 +, Firefox 25+ и 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>

См. это в действии: http://jsfiddle.net/Kg7eA/

URI для браузера Firefox и Chrome для навигации, который позволяет нам создавать файлы, перейдя на URI данных, в то время как IE не поддерживает его в целях безопасности.

С другой стороны, IE имеет API для сохранения blob, который можно использовать для создания и загрузки файлов.

Ответ 7

Это решение извлекается непосредственно из репозитория github tiddlywiki (tiddlywiki.com). Я использовал tiddlywiki почти во всех браузерах и работает как шарм:

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: Загрузите модуль хранителя

Ответ 8

Решение, которое работает на IE10: (Мне нужен файл csv, но это достаточно, чтобы изменить тип и имя файла на 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")

Ответ 9

Если вы просто хотите преобразовать строку, которая будет доступна для загрузки, вы можете попробовать это с помощью jQuery.

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

Ответ 10

var element = document.createElement('a');
element.setAttribute('href', 'data:text/text;charset=utf-8,' +      encodeURI(data));
element.setAttribute('download', "fileName.txt");
element.click();

Ответ 11

Как упоминалось ранее, файловый менеджер - отличный пакет для работы с файлами на стороне клиента. Но с большими файлами это не очень хорошо. StreamSaver.js является альтернативным решением (которое указано в FileServer.js), которое может обрабатывать большие файлы:

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()

Ответ 12

Пакет js-file-download с github.com/kennethjiang/js-file-download обрабатывает крайние случаи для поддержки браузера:

Просмотрите источник, чтобы увидеть, как он использует методы, упомянутые на этой странице.

Установка

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

Usage

Usage
import fileDownload from 'js-file-download'

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

fileDownload(data, 'filename.csv', 'text/csv')

Ответ 13

По состоянию на апрель 2014 года API-интерфейсы FileSytem могут быть не стандартизированы в W3C. Думаю, любой, кто смотрит на решение с помощью blob, должен быть осторожен.

HTML5 рушится

Список рассылки W3C в FileSytem API

Ответ 14

Основываясь на ответе @Rick, который был действительно полезен.

Вы должны просмотреть строку data, если хотите поделиться ею следующим образом:

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

`  Извините, я не могу комментировать @Rick ответ из-за моей текущей низкой репутации в StackOverflow.

Предложение редактировать было разделено и отклонено.

Ответ 16

Эта функция ниже работает.

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

Ответ 17

Для меня это работало отлично, с тем же именем и расширением, загружаемым

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

"title" - это имя файла с расширением, т.е. sample.pdf, waterfall.jpg и т.д.

"file64" является содержание base64 что - то вроде этого, то есть Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO

Ответ 18

Мы можем использовать URL api, в частности URL.createObjectURL(), и Blob api для кодирования и загрузки практически чего угодно.

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

Ответ 19

Если файл содержит текстовые данные, метод, который я использую, заключается в том, чтобы поместить текст в элемент textarea и выбрать его пользователем (щелкните в textarea, затем ctrl-A), затем скопируйте, а затем вставьте в текстовый редактор.

Ответ 20

На самом деле это возможно - используйте Flash.

Вы можете сгенерировать контент с помощью JS, а затем инициализировать некоторые флеш-вары или просто сделать все в флеш-ролике.

Пожалуйста, посмотрите на этот для некоторых важных замечаний.