2014-12-22 3 views
16

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

Это возможно с помощью октет-поток загрузки, поместив его как HREF, как уже упоминалось в этом ответе:

Create a file in memory for user to download, not through server.

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

Но это решение требует «текст», чтобы быть полностью генерироваться перед тем, как толкнул для загрузки, поэтому он должен будет проходить в памяти браузера полностью.

Можно ли передавать текст по мере его создания, используя ТОЛЬКО ЛОГИКУ КЛИЕНТА?

Например:

var inputString = "A"; 
var outStr = ""; 
for(var i = 0; i < 10000000 ; i++) 
{ 
    /* concatenate inputString to output on the go */ 
} 
+0

Если вы не можете найти решение этого вопроса, это может быть альтернативой, чтобы поместить данные в [Blob] (https://developer.mozilla.org/ en-US/docs/Web/API/Blob), а затем используйте [createObjectURL()] (https://developer.mozilla.org/de/docs/Web/API/URL.createObjectURL), чтобы создать ссылку для загрузки , Браузеры, скорее всего, будут кэшировать данные на диске, и особенно у вас не будет большого URL-адреса данных. – Phillip

+0

@Phillip Я не хочу хранить весь контент в блоке или zip-файле или использовать indexDb, это требование является потоковым. – DhruvPathak

+1

нет. все современные технологии браузера требуют знания общего размера перед отправкой первых байтов; только более новые серверные элементы, такие как node.js, могут использовать http1.1 chunking. вам придется использовать много соединений или буфер. вы можете использовать веб-узлы, но для этого потребуется немного настройки на обоих концах. – dandavis

ответ

8

Да & нет. Нет, потому что нет способа писать в файлы с помощью только javascript на стороне клиента. Вроде. Вы можете попросить пользователя загрузить & сохранить файл, но, как вы упомянули, код должен сгенерировать весь файл до того, как это произойдет. Примечание: «Потоком» я предполагаю, что вы имеете в виду поток в файл (постоянно пишите в файл) & по «ТОЛЬКО КЛИЕНТСКАЯ СТОРОНА ЛОГИКА» Я предполагаю, что вы имеете в виду в браузере.

Похоже, что Mozilla работает над тем, как клиентский код взаимодействует с файлами. Вот да. Вид. У них есть свой собственный file system api, который позволяет вам взаимодействовать с файловой системой локальных машин (писать). В частности, есть функция, которая позволяет вам write an input stream to a file. Однако есть несколько звездочек:

1) похоже, что вся система устарела; они побуждают разработчиков использовать OS.file над File I/O

2) Вы должны использовать XPConnect, система, которая позволяет получить доступ к библиотеке XPCOM (компонент Mozilla,) в JavaScript. Если вы хотите сделать это в браузере, похоже, что только расширения Firefox имеют соответствующие разрешения для взаимодействия с этими компонентами(). Если вы не хотите делать это в браузере, вы, очевидно, можете просто использовать узел.

Уверен, что больше осложнений обязательно появятся во время реализации. Но это выглядит как самый верный путь вперед, видя, как OS.File дает вам доступ к функциям, как OS.File.writeAtomic() & основной write to file

Это, как говорится, это не так уж велика по пути, но мы надеемся, что это дает вам твердую отправную точку. Как упоминал @dandavis, браузеры (т. Е. Логика на стороне клиента) предназначены для того, чтобы не допускать такого рода вещи. Это был бы невероятно большой недостаток надзора/безопасности, если бы веб-сайт мог взаимодействовать с локальной файловой системой любого пользователя.

Дополнительные ресурсы:
Wikipedia on XPConnect
Guide on working with XPCOM in javascript - не может быть, что полезно

4

Существует способ сделать это, но она опирается на API Chrome только Filesystem. Мы создадим и напишем во временный файл в изолированной файловой системе и скопируем его в обычную файловую систему, как только мы закончим. Таким образом, вам не нужно хранить весь файл в памяти.Асинхронная версия API Chrome в настоящее время не рассматривается для стандартизации W3C, но синхронная версия (которая использует веб-работников). Если поддержка браузера вызывает беспокойство, то этот ответ не для вас.

API работает следующим образом: Сначала мы получаем функцию requestFileSystem() из браузера. В настоящее время он приставка «WebKit»:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 

Далее мы спрашиваем временный файл система (этот путь нам не нужно спрашивать разрешения пользователя):

var fileSystem; //This will store the fileSystem for later access 
var fileSize = 1024*1024 //Our maximum file system size. 
function errorHandler(e) { 
    console.log('Error: ' + e.name); 
} 
window.requestFileSystem(window.TEMPORARY, fileSize, function (fs) { fileSystem = fs; }, errorHandler); 

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

var fileOptions = { 
    create: true, //If the file is not found, create it 
    exclusive: false //Don't throw an error if the file doesn't exist 
}; 

Здесь мы называем функцию getFile(), которая может создать файл, если он не существует. Внутри обратного вызова мы можем создать новый файл fileWriter для записи в файл. Затем fileWriter перемещается в конец файла, и мы создаем новый блок текста для добавления к нему.

fileSystem.root.getFile(fileName, fileOptions, function(fileEntry) { 
    fileEntry.createWriter(function(fileWriter) { 
     fileWriter.seek(fileWriter.length); 
     var blob = new Blob([STRING_TO_WRITE], {type: 'text/plain'}); 
     fileWriter.write(blob); 
    }, errorHandler); 
}); 

Обратите внимание, что этот API не сохраняется в нормальной пользовательской файловой системе. Вместо этого он сохраняет специальную папку с песочницей. Если вы хотите сохранить его в файловой системе пользователя, вы можете создать ссылку filesystem:. Когда пользователь нажмет на него, он предложит им сохранить его. После их сохранения вы можете удалить временный файл.

Эта функция генерирует ссылку filesystem используя toURL() функцию, fileEntry «s:

var save = function() { 
    var download = document.querySelector("a[download]"); 
    if (!fileSystem) { return; } 
    fileSystem.root.getFile(fileName, {create: false, exclusive: true}, function(fileEntry) { 
    download.href = fileEntry.toURL(); 
    }, errorHandler); 
} 

Используя ссылку с атрибутом загрузки заставит загрузку файла.

<a download></a> 

Вот plunker, который демонстрирует это: http://plnkr.co/edit/q6ihXWEXSOtutbEy1b5G?p=preview

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

Для получения дополнительной информации ознакомьтесь с этим HTML5rocks article или this one, если вы хотите использовать новый, синхронный API Web Worker.

2

Я бы предложил вам путь @quantumwannabe describes, используя временный файл песочницы, чтобы добавить куски.

Но есть новый способ, который может быть использован сегодня (за флагом), но будет включена в следующей версии хрома (52)

А вот где я буду делать @ KeenanLidral-Porter ответить неправильно ,И @quantumwannabe ответить ненужный шаг
Потому что теперь есть способ, чтобы написать поток в файловой системе непосредственно: StreamSaver.js

Он действует, как если бы там был сервер отправки заголовка октет-поток и сообщает браузеру, чтобы загрузить ломти данные с помощью работника службы

const writeStream = streamSaver.createWriteStream('filename.txt') 
const encoder = new TextEncoder 
let data = 'a'.repeat(1024) // Writing some stuff triggers the save dialog to show 
let uint8array = encoder.encode(data + "\n\n") 

writeStream.write(uint8array) // Write some data when you got some 
writeStream.close() // End the saving 
+1

Пожалуйста, опубликуйте объяснение того, как работает эта библиотека, и, возможно, конкретный код API (ов), который он использует, а не только ссылку github. – Bergi

+0

@ Бесконечный 'ReadableStream' доступен на хромированном хроме 50 – guest271314