问题描述
我正在与文件系统提供程序一起使用loopback-component-storage来上传照片.效果很好.但是现在我有一个请求,可以将照片导出/下载"到zip存档中.
I'm using loopback-component-storage with the filesystem provider to upload photos. It works great. But now I have a request to 'export/download' photos to a zip archive.
我整理了一些代码,以从文件存储示例中将另一种方法downloadContainer()
添加到Container
.它使用Archiver
模块,一切似乎都可以正常工作,但是在我调用zip.finalize()
后浏览器崩溃了,我希望得到一个save file
对话框,而不是...
I've put together some code to add another method, downloadContainer()
to Container
from the file-storage example. It uses the Archiver
module, everything seems to work fine, but the browser crashes after I call zip.finalize()
I'm expecting to get a save file
dialog box instead...
到目前为止,这是我的代码:
Here is my code so far:
Container.downloadContainer = function(container, files, res, cb) {
var DELIM, _appendFile, _finalize, _oneComplete, _remaining, filenames, storageService, zip;
zip = Archiver('zip');
zip.pipe(res);
storageService = this;
_remaining = {};
_appendFile = function(zip, container, filename) {
var reader;
console.log('appendFile=' + filename);
reader = storageService.downloadStream(container, filename, function(stream) {
return console.log('storageService.downloadStream() resp=', _.keys(stream));
});
zip.append(reader, {
name: filename
});
};
zip.on('error', function(err) {
console.log('zip entry error', err);
res.status(500).send({
error: err.message
});
});
zip.on('entry', function(o) {
return _oneComplete(o.name);
});
_oneComplete = function(filename) {
delete _remaining[filename];
console.log('_oneComplete(): ', {
remaining: _.keys(_remaining),
size: zip.pointer()
});
if (_.isEmpty(_remaining)) {
_finalize();
}
};
_finalize = function() {
console.log('calling zip.finalize() ...');
res.on('close', function() {
console.log('response closed');
res.attachment(container + '.zip');
return res.status(200).send('OK').end();
});
zip.finalize();
};
if (files === 'all' || _.isEmpty(files)) {
console.log('files=', files);
storageService.getFiles(container, function(err, ssFiles) {
_remaining = _.object(_.pluck(ssFiles, 'name'));
console.log('filenames=', _.keys(_remaining));
return ssFiles.forEach(function(file) {
_appendFile(zip, container, file.name);
});
});
}
}
这就是我在控制台中看到的内容
and here is what I see in the console
// log
files= all
filenames= [ 'IMG_0799.PNG', 'IMG_0800.PNG', 'IMG_0801.PNG', 'IMG_0804.PNG' ]
appendFile=IMG_0799.PNG
appendFile=IMG_0800.PNG
appendFile=IMG_0801.PNG
appendFile=IMG_0804.PNG
_oneComplete(): { remaining: [ 'IMG_0800.PNG', 'IMG_0801.PNG', 'IMG_0804.PNG' ],
size: 336110 }
_oneComplete(): { remaining: [ 'IMG_0801.PNG', 'IMG_0804.PNG' ], size: 460875 }
_oneComplete(): { remaining: [ 'IMG_0804.PNG' ], size: 1506464 }
_oneComplete(): { remaining: [], size: 1577608 }
calling zip.finalize() ...
// then browser crash
推荐答案
此代码扩展了以上Bryan的建议,并与provider=filesystem
This code expands on the suggestion from Bryan above and works with provider=filesystem
Archiver = require('archiver')
module.exports = function(Container) {
Container.downloadContainer = function(container, files, res, cb) {
var DELIM, _appendFile, _finalize, _oneComplete, _remaining, filenames, storageService, zip, zipFilename;
zip = Archiver('zip');
zipFilename = container + '.zip';
storageService = this;
_remaining = {};
_appendFile = function(zip, container, filename) {
var reader;
reader = storageService.downloadStream(container, filename);
zip.append(reader, {
name: filename
});
console.log("appending", {
name: filename
});
};
res.on('close', function() {
console.log('Archive wrote %d bytes', zip.pointer());
return res.status(200).send('OK').end();
});
res.attachment(zipFilename);
zip.pipe(res);
zip.on('error', function(err) {
console.log('zip entry error', err);
res.status(500).send({
error: err.message
});
});
zip.on('entry', function(o) {
return _oneComplete(o.name);
});
_oneComplete = function(filename) {
delete _remaining[filename];
console.log('_oneComplete(): ', {
remaining: _.keys(_remaining),
size: zip.pointer()
});
if (_.isEmpty(_remaining)) {
_finalize();
}
};
_finalize = function() {
console.log('calling zip.finalize() ...');
zip.finalize();
};
if (files === 'all' || _.isEmpty(files)) {
console.log('downloadContainer, files=', files);
storageService.getFiles(container, function(err, ssFiles) {
_remaining = _.object(_.pluck(ssFiles, 'name'));
return ssFiles.forEach(function(file) {
_appendFile(zip, container, file.name);
});
});
} else {
DELIM = ',';
filenames = files.split(DELIM);
_remaining = _.object(filenames);
console.log('filenames=', _.keys(_remaining));
_.each(filenames, function(filename) {
_appendFile(zip, container, filename);
});
}
};
Container.remoteMethod('downloadContainer', {
shared: true,
accepts: [
{
arg: 'container',
type: 'string',
'http': {
source: 'path'
}
}, {
arg: 'files',
type: 'string',
required: false,
'http': {
source: 'path'
}
}, {
arg: 'res',
type: 'object',
'http': {
source: 'res'
}
}
],
returns: [],
http: {
verb: 'get',
path: '/:container/downloadContainer/:files'
}
});
这篇关于Strongloop回送存储服务:如何使用StorageService.downloadStream()下载容器中所有照片的ZIP?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!