Не удается скачать динамически созданный ZIP-архив - PullRequest
0 голосов
/ 15 октября 2018

Я пытаюсь динамически записать вывод запросов MySQL в архив.Вот мой код:

var async = require("async");
var mysql = require("mysql");
var express = require("express"); 
var archiver = require("archiver");

var app = express();

var connection = mysql.createConnection({
   host     : 'localhost',
   user     : 'root',
   password : 'password',
   database : 'test'
});

app.get('/file', (req, res) => {

    res.writeHead(200, {
        'Content-Type': 'application/zip',
        'Content-disposition': 'attachment; filename=archive-name.zip'

    var zip = archiver('zip', {
        zlib: { level: 9 } 
    });

    zip.pipe(res); 

    zip.on('end', function() {
        console.log('Archive wrote %d bytes', zip.pointer());
    });

    const queriesArray = ["SELECT * FROM tb1", "SELECT * FROM tb2"];

    async.forEachOf(queriesList, (query) => {
        connection.query(query, (err, results) => {
            if(!err) {
                zip.append(JSON.stringify(results), {name: `${query}.txt`})
            }
            else {
                console.log("Error while performing Query");
            }
        })
    }, function(err) {
           if (err) {
               console.log("error")
           }
           else {
               zip.finalize();
           }
       }) 
})

const port = process.env.PORT || 7000;
app.listen(port, () => {
    console.log('Listen on port ' + port);
})

Этот код должен создавать zip-архив с несколькими текстовыми файлами.Пользователь, посещающий страницу /file, должен получить приглашение на загрузку файла, но кажется, что zip.finalize() не работает, поэтому я не могу загрузить созданный архив (загрузка начинается, когда я посещаю /file, но не заканчивается).Почему мой код не работает?

1 Ответ

0 голосов
/ 15 октября 2018

Это потому, что ваша функция обратного вызова никогда не вызывается как forEachOf, которая не знает, что она выполнила все асинхронные задачи.

Функция iteratee имеет последний аргумент, который является функцией обратного вызова, которую вы должны вызвать, чтобы знать, что этот конкретный асинхронный процесс завершился, но вы никогда не используете его.

https://caolan.github.io/async/global.html#AsyncFunction

«Асинхронная функция» в контексте Асинхронная - это асинхронная функция с переменным числом параметров, причем последний параметр является обратным вызовом.(function (arg1, arg2, ..., callback) {}) Финальный обратный вызов имеет вид callback(err, results...), , который должен быть вызван после завершения функции.

Поэтому для исправления кода обязательно вызовите обратный вызовметод вашей функции iteratee внутри обратного вызова вашего запроса call

async.forEachOf(queriesList, (query,key,callback) => {
    connection.query(query, (err, results) => {
        if(!err) {
            zip.append(JSON.stringify(results), {name: `${query}.txt`})
        }
        else {
            console.log("Error while performing Query");
        }
        callback();
    })
...