it-roy-ru.com

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

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

696
Joseph Silber

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

<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 demo .

381
Matthew Flaschen

Простое решение для 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>

Использование

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

Все вышеприведенные примеры прекрасно работают в 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);
169
naren

Все вышеперечисленные решения не работают во всех браузерах. Вот что в итоге работает на 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 (), когда они вам больше не нужны. Браузеры выпустят их автоматически, когда документ выгружен; однако для оптимальной производительности и использования памяти, если есть безопасные времена, когда вы можете явно выгружать их, вы должны сделать это.

162
Ludovic Feltz

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

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

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

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

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

22
dinesh ygv

Это решение извлекается непосредственно из репозитория 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: Скачать модуль заставки

11
Danielo515

Решение, которое работает на 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")
10
Dzarek

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

$('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

Как упоминалось ранее, filesaver - отличный пакет для работы с файлами на стороне клиента. Но это не очень хорошо с большими файлами. 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()
6
مصطفی

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

HTML5 качается головой

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

5
pravin

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

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

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

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

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

5
atfornes

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

3
owencm

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

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

Installation

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

Использование

import fileDownload from 'js-file-download'

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

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

Для меня это сработало идеально, с тем же именем файла и расширения загружается

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

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

'file64' - это содержимое base64, например, Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO

0
abdul

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

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