本文介绍了Strongloop回送存储服务:如何使用StorageService.downloadStream()下载容器中所有照片的ZIP?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与文件系统提供程序一起使用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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 15:54