如何通过管道将存档 (zip) 传输到 S3 存储桶

Pet*_*oss 6 javascript archive amazon-s3 node.js

我对如何继续感到有些困惑。我使用存档(节点 js 模块)作为将数据写入 zip 文件的一种方式。目前,当我写入文件(本地存储)时,我的代码可以正常工作。

var fs = require('fs');
var archiver = require('archiver');

var output = fs.createWriteStream(__dirname + '/example.zip');
var archive = archiver('zip', {
     zlib: { level: 9 }  
});

archive.pipe(output);
archive.append(mybuffer, {name: ‘msg001.txt’});
Run Code Online (Sandbox Code Playgroud)

我想修改代码,以便存档目标文件是 AWS S3 存储桶。查看代码示例,我可以在创建存储桶对象时指定存储桶名称和键(和主体),如下所示:

var s3 = new AWS.S3();
var params = {Bucket: 'myBucket', Key: 'myMsgArchive.zip' Body: myStream};
s3.upload( params, function(err,data){
    … 
});

Or 

s3 = new AWS.S3({ parms: {Bucket: ‘myBucket’ Key: ‘myMsgArchive.zip’}});
s3.upload( {Body: myStream})
    .send(function(err,data) {
    …
    });
Run Code Online (Sandbox Code Playgroud)

关于我的 S3 示例,myStream似乎是一个可读的流,我很困惑如何根据archive.pipe可写流的要求进行工作。这是我们需要使用传递流的地方吗?我找到了一个示例,其中有人创建了一个传递流,但该示例过于简洁,无法正确理解。我所指的具体例子是:

将流通过管道传输到 s3.upload()

任何人可以给我的任何帮助将不胜感激。谢谢。

小智 7

这对于想知道如何使用pipe.

由于您使用传递流正确引用了示例,因此这是我的工作代码:

1 - 例程本身,使用node-archiver压缩文件

exports.downloadFromS3AndZipToS3 = () => {
  // These are my input files I'm willing to read from S3 to ZIP them

  const files = [
    `${s3Folder}/myFile.pdf`,
    `${s3Folder}/anotherFile.xml`
  ]

  // Just in case you like to rename them as they have a different name in the final ZIP

  const fileNames = [
    'finalPDFName.pdf',
    'finalXMLName.xml'
  ]

  // Use promises to get them all

  const promises = []

  files.map((file) => {
    promises.push(s3client.getObject({
      Bucket: yourBubucket,
      Key: file
    }).promise())
  })

  // Define the ZIP target archive

  let archive = archiver('zip', {
    zlib: { level: 9 } // Sets the compression level.
  })

  // Pipe!

  archive.pipe(uploadFromStream(s3client, 'someDestinationFolderPathOnS3', 'zipFileName.zip'))

  archive.on('warning', function(err) {
    if (err.code === 'ENOENT') {
      // log warning
    } else {
      // throw error
      throw err;
    }
  })

  // Good practice to catch this error explicitly
  archive.on('error', function(err) {
    throw err;
  })

  // The actual archive is populated here 

  return Promise
    .all(promises)
    .then((data) => {
      data.map((thisFile, index) => {
        archive.append(thisFile.Body, { name: fileNames[index] })
      })

      archive.finalize()
    })
  }
Run Code Online (Sandbox Code Playgroud)

2 - 辅助方法

const uploadFromStream = (s3client) => {
  const pass = new stream.PassThrough()

  const s3params = {
    Bucket: yourBucket,
    Key: `${someFolder}/${aFilename}`,
    Body: pass,
    ContentType: 'application/zip'
  }

  s3client.upload(s3params, (err, data) => {
    if (err)
      console.log(err)

    if (data)
      console.log('Success')
  })

  return pass
}
Run Code Online (Sandbox Code Playgroud)


h-k*_*ppo 5

以下示例采用已接受的答案,并使其按要求处理本地文件。

const archiver = require("archiver")
const fs = require("fs")
const AWS = require("aws-sdk")
const s3 = new AWS.S3()
const stream = require("stream")

const zipAndUpload = async () => {
  const files = [`test1.txt`, `test2.txt`]
  const fileNames = [`test1target.txt`, `test2target.txt`]
  const archive = archiver("zip", {
    zlib: { level: 9 } // Sets the compression level.
  })
  files.map((thisFile, index) => {
    archive.append(fs.createReadStream(thisFile), { name: fileNames[index] })
  })
  const uploadStream = new stream.PassThrough()
  archive.pipe(uploadStream)
  archive.finalize()
  archive.on("warning", function (err) {
    if (err.code === "ENOENT") {
      console.log(err)
    } else {
      throw err
    }
  })
  archive.on("error", function (err) {
    throw err
  })
  archive.on("end", function () {
    console.log("archive end")
  })
  await uploadFromStream(uploadStream)
  console.log("all done")
}

const uploadFromStream = async pass => {
  const s3params = {
    Bucket: "bucket-name",
    Key: `streamtest.zip`,
    Body: pass,
    ContentType: "application/zip"
  }
  return s3.upload(s3params).promise()
}

zipAndUpload()
Run Code Online (Sandbox Code Playgroud)