Как отправить сжатую строку клиенту с узла, на котором работает Koa? - PullRequest
0 голосов
/ 12 декабря 2018

Я хочу отправить очень большую сжатую строку JSON клиенту.

Я перепробовал много методов, проиллюстрированных в документах koa и node, но я не могу обернуть голову в ожидании koa для потоковой передачи / передачи его объекту context.response.body.

Я пытался

const buf = Buffer.from(json, 'utf-8');   
zlib.gzip(buf, function (_, result) {  
    ctx.request.body = result;                     
});

на основе этого вопроса stackoverflow.

Также:

var input = new Buffer(json, 'utf8')
ctx.request.body = zlib.deflate(input)

как

var input = new Buffer(json, 'utf8')
ctx.request.body = zlib.deflate(input).toString('utf8')

на основе этого вопроса stackoverflow.

Я также пытался использовать архиватор:

const archive = archiver.create('zip', {});
archive.pipe(ctx.body);
archive.append(JSON.stringify(json), { name: 'libraries.json'});
archive.finalize();

В большинстве случаев либоклиент получает искаженный zip / файл или index.html в виде файла.

Я также пытался использовать koa-compress , используя этот вопрос о переполнении стека в качестве руководства.

app.use(compress({
    filter: function (content_type: any) {
        return /text/i.test(content_type);
    },
    threshold: 2048,
    flush: require('zlib').Z_SYNC_FLUSH
}));

...

ctx.response.type = 'application/json';
ctx.body = json;
ctx.compress = true;
ctx.status = 200;

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

HTTP/1.1 200 OK
X-Powered-By: Express
vary: Accept-Encoding
last-modified: Thu, 01 Nov 2018 21:26:55 GMT
cache-control: max-age=0
content-type: application/json; charset=utf-8
content-length: 4767074
date: Tue, 11 Dec 2018 23:44:11 GMT

Клиент пытается использовать трюк "создать блоб" для загрузки файла:

const xhr = new XMLHttpRequest();
const default_headers = {
    'Content-Type': 'application/json',
};
xhr.open('GET', `${API_URL}${url}`);
for (let header in default_headers) {
    xhr.setRequestHeader(header, default_headers[header]);
}
xhr.onload = function() {
    if (this.status === 200) {
        // Create a new Blob object using the response data of the onload object
        var blob = new Blob([this.response], { type: 'application/json' });
        // Create a link element, hide it, direct it towards the blob, and then 'click' it programatically
        let a = document.createElement('a');
        a.style = 'display: none';
        document.body.appendChild(a);
        // Create a DOMString representing the blob and point the link element towards it
        let url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = 'libraries.json';
        // have also tried libraries.zip, .gzip, etc
        // programatically click the link to trigger the download
        a.click();
        // release the reference to the file by revoking the Object URL
        window.URL.revokeObjectURL(url);
    }
};
xhr.responseType = 'blob';
xhr.send();

Я также пытался заставить клиента сделать запрос "vanilla" безлюбые хитростиЗатем диалоговое окно «Загрузка файла» не запускается.

Я ожидаю, что с моей стороны есть фундаментальное недоразумение относительно AJAX и загрузки файлов.

Как разрешить клиенту браузера запрашивать, а затем загружать (очень большое) сжал JSON с узла сервера, на котором работает Koa ?

1 Ответ

0 голосов
/ 01 февраля 2019

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

https://www.npmjs.com/package/koa-compress https://github.com/koajs/compress

Так просто, как это:

const responseBodyCompressor = require("koa-compress");
...
app.use( responseBodyCompressor() )
...
...