以下代码用于从我们的Web应用程序中获取.zip
文件。该文件是通过安全地关闭另一个应用程序然后压缩,最后发送它下载来生成的。
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。这需要使用id
来完成,这样两个用户就不会创建冲突的文件。
答案 0 :(得分: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); });
答案 1 :(得分:0)
您可以使用异步实用程序库,例如async。
您正在寻找的模式似乎是waterfall模式。 这样您就可以将所需的数据从一个任务传递到另一个任务。
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);
}