Я хочу загрузить зашифрованный файл со своего сервера, расшифровать его и сохранить локально. Я хочу расшифровать файл и записать его локально по мере его загрузки, а не ждать завершения загрузки, расшифровать его, а затем поместить расшифрованный файл в тег привязки. Основная причина, по которой я хочу это сделать, заключается в том, чтобы при больших файлах браузеру не приходилось хранить в памяти сотни мегабайт или несколько гигабайт.
JavaScript: запись в поток загрузки
Ответы (2)
Это будет возможно только с комбинацией сервис-воркер + выборка + поток. В некоторых браузерах есть работник и выборка, но еще меньше поддерживают выборку с потоковой передачей (Blink)
new Response(new ReadableStream({...}))
Я создал библиотеку для сохранения потоковых файлов для связи с работником службы в другом месте для перехвата сетевого запроса: StreamSaver.js< /а>
Это немного отличается от потока узла, вот пример
function unencrypt(){
// should return Uint8Array
return new Uint8Array()
}
// We use fetch instead of xhr that has streaming support
fetch(url).then(res => {
// create a writable stream + intercept a network response
const fileStream = streamSaver.createWriteStream('filename.txt')
const writer = fileStream.getWriter()
// stream the response
const reader = res.body.getReader()
const pump = () => reader.read()
.then(({ value, done }) => {
let chunk = unencrypt(value)
// Write one chunk, then get the next one
writer.write(chunk) // returns a promise
// While the write stream can handle the watermark,
// read more data
return writer.ready.then(pump)
)
// Start the reader
pump().then(() =>
console.log('Closed the stream, Done writing')
)
})
Есть также два других способа получить потоковый ответ с помощью xhr, но они не являются стандартными и не имеют значения, если вы их используете (responseType = ms-stream || moz-chunked-arrayBuffer), потому что StreamSaver зависит от fetch + ReadableStream любыми способами и не может использоваться никаким другим образом
Позже вы сможете сделать что-то подобное, когда также будут реализованы потоки WritableStream + Transform.
fetch(url).then(res => {
const fileStream = streamSaver.createWriteStream('filename.txt')
res.body
.pipeThrogh(unencrypt)
.pipeTo(fileStream)
.then(done)
})
Также стоит упомянуть, что менеджер загрузки по умолчанию обычно связан с фоновой загрузкой, поэтому люди иногда закрывают вкладку, когда видят загрузку. Но все это происходит в основном потоке, поэтому вам нужно предупредить пользователя, когда он уйдет.
window.onbeforeunload = function(e) {
if( download_is_done() ) return
var dialogText = 'Download is not finish, leaving the page will abort the download'
e.returnValue = dialogText
return dialogText
}
из соображений безопасности браузеры не позволяют передавать входящий читаемый поток непосредственно в локальную файловую систему, поэтому у вас есть 2 способа решить эту проблему:
window.open(Resourse_URL)
: загрузить ресурс в новом окне с Content_Disposition, установленным на "вложение";<a download href="path/to/resourse"></a>
: использование атрибута "download" AnchorElement для загрузки потока на жесткий диск;
надеюсь, это поможет :)
ReadableStream
, см. JS Promise — мгновенно получить некоторые данные из функции, которая возвращает Promise - person guest271314   schedule 25.09.2016Blob
илиArrayBuffer
, поскольку данные передаются в потоковом режиме после любых процессов расшифровки; затем используйтеcreateObjectURL
илиdata URI
данных для загрузки пользователем после завершения потока - person guest271314   schedule 25.09.2016the browser does not have to store hundreds of megabytes or several gigabytes in memory.
- person Jaromanda X   schedule 25.09.2016nodejs
. Здесь хотелось бы, чтобы весь поток был завершен и проверен, прежде чем предлагать файл для загрузки. Что, если 100 МБ файла в порядке, хотя последний байт поврежден? - person guest271314   schedule 25.09.2016browserify
для использованияnodejs
в браузере. - person guest271314   schedule 25.09.2016nodejs
обычно не предназначен для использования в браузере. Пытался дать ссылку на иллюстрации использования.pipe()
. Обработайте данные на сервере или дажеWorker
, затем предложите скачать. Опять же, не уверен, как файл может быть загружен в виде потока. Ближайшим просмотренным является файл.zip
, который заполняется по мере загрузки. Каков размер файла, который будет загружен? - person guest271314   schedule 25.09.2016What is the size of the file that will be downloaded?
- это в вопросе - person Jaromanda X   schedule 25.09.2016requestFileSystem
, а затем использовать.toURL()
, чтобы предложить загрузку. Хотя, по общему признанию, не пытались добавлять символы к наборуdata URI
в элементеa
href
после того, как пользователь щелкнул якорь. - person guest271314   schedule 25.09.2016Blob
иArrayBuffer
; хотя, опять же, не пробовал добавлять байты кBlob
илиArrayBuffer
, поскольку байты загружаются в локальный файл. - person guest271314   schedule 25.09.2016data URI
послеclick
в<a>
с атрибутомdownload
, и байты были добавлены к сохраненному файлу. Таким образом, это может быть возможно jsfiddle.net/6xazmmpp - person guest271314   schedule 25.09.2016i < 100000
, вкладка разбилась - person guest271314   schedule 25.09.2016