1

以下代码用于.zip从我们的 Web 应用程序中获取文件。该文件是通过安全关闭另一个应用程序然后压缩生成的,最后将其发送以供下载。

var dl = function() {
    request({
        method: 'GET',
        uri: 'some_url',
        headers: {
            'User-Agent': 'Scripted-Download'
        },
        encoding: null,
        jar: true
    }, function(err, res, body) {
        if (err) throw(err)
        if (res.headers['content-type'] === 'application/zip;charset=utf-8') {
            process.stdout.write('\rDownloading file ..')
            var id = uuid.v4()
            , file = path.resolve(__dirname, '../../' + id + '.zip')
            fs.writeFile(file, body, function(err) {
                if (err) throw(err)
                process.stdout.write('\rFile downloaded ' + id + '.zip')
                process.exit(0)
            })
        } else {
            process.stdout.write('\rAwaiting file ..')
            setTimeout(dl(), 30 * 1000)
        }
    })
}

这按预期工作。但是,我需要从另一个脚本中使用它。所以上面的代码返回一个id下载的文件,然后我可以从另一个脚本中提取.zip并将提取的文件放入具有相同id. 然后这些文件将可供下载。

编辑基本上我需要执行这个脚本,在下载内容时提取内容,然后res.render()在前两个步骤完成时加载 UI。这需要使用 a 来完成,id这样两个用户就不会创建冲突的文件。

4

2 回答 2

3

正如评论中提到的,承诺应该让这一切变得容易。首先承诺您需要的异步功能:

function makeRequest(parameters) {
    return new Promise(function (resolve, reject) {
        request(parameters,  function (err, res, body) {
            if (err) { reject (err); }
            else { resolve({ res: res, body: body }); }
        });
    });
}

function writeFile(file, body) {
    return new Promise(function (resolve, reject) {
        fs.writeFile(file, body, function(err) {
            if (err) { reject(err); }
            else { resolve(); }
        });
    });
}

function timeout(duration) {
    return new Promise(function (resolve) {
        setTimeout(resolve, duration);
    });
}

然后使用它们。

var dl = function () {
    return makeRequest({
        method: 'GET',
        uri: 'some_url',
        headers: {
            'User-Agent': 'Scripted-Download'
        },
        encoding: null,
        jar: true
    }).then(function (result) {
        if (result.res.headers['content-type'] === 'application/zip;charset=utf-8') {
            process.stdout.write('\rDownloading file ..')
            var id = uuid.v4()
            , file = path.resolve(__dirname, '../../' + id + '.zip');

            return writeFile(file, result.body)
                .then(function () { return id; });
        } else {
            process.stdout.write('\rAwaiting file ..');

            return timeout(30 * 1000).then(dl);
        }
    });
}

dl().then(function (id) { process.stdout.write('\rid is: ' + id); });
于 2016-10-26T09:54:26.587 回答
0

您可以使用异步实用程序库,例如async

您正在寻找的模式似乎是瀑布模式。这将允许您将所需的数据从一项任务传递到另一项任务。

function requestFile(cb){
    request({
        method: 'GET',
        uri: 'some_url',
        headers: {
           'User-Agent': 'Scripted-Download'
        },
        encoding: null,
        jar: true
    }, function(err, res, body) {
       if (err) throw(err)
       if (res.headers['content-type'] === 'application/zip;charset=utf-8') {
           process.stdout.write('\rDownloading file ..');
           cb(null, body);
       }
       else{ 
           process.stdout.write('\rAwaiting file ..');
           setTimeout(requestFile, 30 * 1000)
       }
   });
}


function saveFile(body, cb){
    var id = uuid.v4()
      , file = path.resolve(__dirname, '../../' + id + '.zip')
    fs.writeFile(file, body, function(err) {
        if (err) throw(err)
        process.stdout.write('\rFile downloaded ' + id + '.zip');
        cb(null, id);
    })
}

function render(id, cb) {
   //do what ever you need with your id
   cb();
}   

async.waterfall([
    requestFile,
    saveFile,
    render
], function(err){

});

顺便说一句,我建议您将数据从服务器直接流式传输到磁盘,而不是将其全部收集在缓冲区中然后保存。

您可以在请求对象上创建data侦听器,然后将它们直接流式传输到磁盘,甚至只是使用request.pipe(file)

例子:

function streamFile(){

    var id = uuid.v4()
        , file = path.resolve(__dirname, '../../' + id + '.zip');
    var stream = fs.createWriteStream(file);
    stream.on('error', function(err){
        throw err;
    }).on('close', function(){
        process.stdout.write('\rFile downloaded ' + id + '.zip')
    });

    request({
        method: 'GET',
        uri: 'some_url',
        headers: {
           'User-Agent': 'Scripted-Download'
        },
        encoding: null,
        jar: true
    }).on('error', function(err) {
        throw(err)
    }).on('response', function(res){
        if (res.headers['content-type'] === 'application/zip;charset=utf-8') {
            process.stdout.write('\rDownloading file ..');
            cb(null, body);
        }
        else{
            process.stdout.write('\rAwaiting file ..');
            res.destroy();
            setTimeout(streamFile, 30 * 1000)
        }
    }).pipe(stream);
}
于 2016-10-26T09:40:19.460 回答