Loopback:如何将文件从一个容器复制到另一个容器?

Loopback: How to copy files from one container to another?

我正在使用 Strongloop loopback 作为我的后端 API。 我正在使用它的 loopback-component-storage 来上传和管理文件。更具体地说,我目前正在使用文件系统,但在生产环境中将切换到 AWS 存储。

平台用户可以复制项目,因此也会复制已上传的链接文件。

我的问题是,如何将文件从一个容器复制到另一个容器?

到目前为止,这是我创建新容器的代码:

    Project.app.models.storage.getContainer(templateId, function (err, container) {
    if(err){
        // If error, no docs have been added or created, so just skip                        
        return;
    }
    Project.app.models.storage.createContainer({ name: projectId},function (err,container) {
    if(err){
       console.log("Error creating a container when copying project");
       return;
    }
    // Here is where I need assistance
    });
});

可以创建下载流,然后通过管道将流从一个容器上传到另一个容器,但这不是一个好主意,因为您会产生不必要的流量。让您的底层环境为您完成这项工作。

在您的本地开发环境中,您可以使用 fs 模块来处理文件,但是当您将存储迁移到 S3 时,您应该使用 AWS SDK 来复制文件。您可以在存储模型上创建远程方法,它将使用源 bucket/folder 和目标 bucket/folder 为您复制文件。

类似于:

  Storage.remoteMethod(
    'copyS3File',
    {
      accepts: [
        {arg: 'copySource', type: 'string'},
        {arg: 'destinationBucket', type: 'string'},
        {arg: 'destinationFileName', type: 'string'}],
      returns: {arg: 'success', type: 'string'}
    }
  );

  Storage.copyS3File = function(copySource, destinationBucket, destinationFileName, cb) {
    var AWS = require('aws-sdk');
    var s3 = new AWS.S3({params: {Bucket: 'yourbucket',region:'yourregion'}});
    var params = {CopySource: copySource, Bucket: destinationBucket, Key: destinationFileName};
    s3.copyObject(params, function(err, success) {
      if (err) cb(err); // an error occurred
      else     cb(null, success)           // successful response
    });
  });

参见 S3 上的 Calling the copyObject operation

请注意,此代码未经测试或准备投入生产。它在这里只是给你一个想法如何去做。

另请注意,S3 与存储的 loopbackjs 实现有些不同。 S3 具有扁平结构,但支持使用键名前缀组织文件夹中的文件。

Working with S3 folders

为了使事情更清楚,您可以从源容器中检索文件列表并循环遍历该列表以使用上面创建的远程方法将文件复制到新目标,例如:

Storage.getFiles({container: 'yourContainer'}, function(files){

  files.forEach(function(file){
    Storage.copyS3File(file.container + '/' + file.name, 'newContainer', 'newFile.name', cb);
  });

}, function(err){
  console.log(err);
});

为文件系统提供者做这个的想法

  1. 使用 storage.GetFiles('container-name',callback)
  2. 从要从中复制文件的容器中获取文件列表
  3. 使用存储创建要在其中复制这些文件的容器。创建容器()
  4. 使用 storage.uploadStream('recently- created-container', 'file-name')
  5. 获取用于上传的流
  6. 获取文件的读取流并通过管道传输读写操作
  7. 对每个文件重复第 3 步和第 4 步(或者您可以根据需要链接流)

在您的案例中,代码如下所示

Project.app.models.storage.getContainer(templateId, function (err, container) {
    if(err || !container){
        // If error, no docs have been added or created, so just skip
        return;
    }
    Project.app.models.storage.getFiles(templateId, function (err, files) {
        if(err){
            // If error, no docs have been added or created, so just skip
            return;
        }
      Project.app.models.storage.createContainer({ name: projectId},function (err,newcontainer) {
        if(err || !newcontainer){
           console.log("Error creating a container when copying project");
           return;
         }
         files.forEach(function(file){
           var writer = container.uploadStream(newcontainer.name, file.name);
            require('fs').createReadStream('path-to-storage-directory/'+container.name+'/'+file.name).pipe(writer);
            writer.on('finish', function(err,done){
              console.log('finished writing file'+file.name)
            });
            writer.on('error', function(err){
              console.log('error in copying file'+file.name,err)
            });
         });
      });
  })
})