Создание ZIP-архива в памяти с архиватором, а затем отправка этого файла клиенту с koa на сервер узла - PullRequest
0 голосов
/ 05 декабря 2018

Мне (как серверу узлов с каркасом Koa) нужно взять BLOB-объект JSON, превратить его в файл с расширением .json, затем вставить его в zip-архив, а затем отправить архив в виде вложенного файла в ответ назапрос от клиента.

Кажется, способ сделать это - использовать инструмент Archiver .Насколько я понимаю, способ сделать это состоит в том, чтобы создать архив, добавить к нему блог json в виде файла .json (он автоматически создает файл в архиве?), А затем направить этот .zip в объект ответа.,В парадигме "трубопровода" мое понимание терпит неудачу, в основном из-за того, что я не понимаю, о чем говорят эти документы.

Документация архиватора , а также некоторые stackoverflow ответы , используйте язык, который для меня означает "поток данных на клиент по трубопроводу (zip-файл) кОбъект ответа HTTP. В Koa docs говорится, что ctx.body может быть установлен непосредственно в поток, поэтому я попробовал вот что:

Попытка 1

    const archive = archiver.create('zip', {});
    ctx.append('Content-Type', 'application/zip');
    ctx.append('Content-Disposition', `attachment; filename=libraries.zip`);
    ctx.response.body = archive.pipe(ctx.body);
    archive.append(JSON.stringify(blob), { name: 'libraries.json'});
    archive.finalize();

Логика: тело ответа должно быть установлено в поток, и этот поток должен быть потоком архиватора (указывающим на ctx.body).

Результат: файл .zip загружается на стороне клиента, однако почтовый индекс каким-то образом деформирован (не может открыться).

Попытка 2

    const archive = archiver.create('zip', {});
    ctx.append('Content-Type', 'application/zip');
    ctx.append('Content-Disposition', `attachment; filename=libraries.zip`);
    archive.pipe(ctx.body);
    archive.append(JSON.stringify(blob), { name: 'libraries.json'});
    archive.finalize();

Логика: установка тела в качестве потока после, э-э,«нацеливание потока на него» кажется глупым, поэтому вместо этого скопируйте другие примеры стекового потока.

Результат: То же, что и попытка 1.

Попытка 3

Основано на https://github.com/koajs/koa/issues/944

    const archive = archiver.create('zip', {});
    ctx.append('Content-Type', 'application/zip');
    ctx.append('Content-Disposition', `attachment; filename=libraries.zip`);
    ctx.body = ctx.request.pipe(archive);
    archive.append(JSON.stringify(body), { name: 'libraries.json'});
    archive.finalize();

Результат: ctx.request.pipe - это не функция.

Возможно, я не правильно читаю, но всеКажется, ng online указывает на то, что archive.pipe(some sort of client-sent stream) «магически просто работает». Это цитата из файла примера архивного инструмента , «потоковая магия» - это слова, которые они используют.

Как в оперативной памяти превратить большой двоичный объект JSON в файл .json, а затем добавить этот файл .json к .zip, который затем отправляется клиенту и загружается, а затем может быть успешно разархивирован всм. json ?

РЕДАКТИРОВАТЬ: Если я console.log ctx.body после archive.finalize(), он показывает ReadableStream, что кажется правильным.Однако у него есть свойство «путь», которое меня беспокоит - его index.html, о котором я задумывался, - в «предварительном просмотре ответа» на стороне клиента я вижу строковую версию нашего index.html.Файл все еще загружал .zip, так что я не был слишком обеспокоен, но теперь мне интересно, связано ли это.

РЕДАКТИРОВАТЬ2: Если заглянуть глубже в ответ на стороне клиента, кажется, что отправленные обратно данные прямо в наш index.html, так что теперь я очень запутался.

1 Ответ

0 голосов
/ 11 марта 2019

Да, вы можете напрямую установить ctx.body в поток.Коа позаботится о трубопроводе.Нет необходимости вручную что-либо передавать (если вы, например, не хотите передавать в журнал).

const archive = archiver('zip');

ctx.type = 'application/zip';
ctx.response.attachment('test.zip');
ctx.body = archive;

archive.append(JSON.stringify(blob), { name: 'libraries.json' });
archive.finalize(); 
...