aws sdk 使用node.js分段上传到s3

Adi*_*chs 14 amazon-s3 amazon-web-services node.js aws-sdk aws-sdk-nodejs

我正在尝试使用 node.js 将大文件上传到 s3 存储桶aws-sdk

该方法以分段上传的V2方式upload对文件进行整体上传。

我想使用新的 V3 aws-sdk。新版本如何上传大文件?该方法PutObjectCommand似乎没有做到这一点。

我见过一些方法,CreateMultiPartUpload但我似乎找不到使用它们的完整工作示例。

提前致谢。

Gus*_*eca 15

截至 2021 年,我建议使用lib-storage包,它抽象了很多实现细节。

示例代码:

import { Upload } from "@aws-sdk/lib-storage";
import { S3Client, S3 } from "@aws-sdk/client-s3";

const target = { Bucket, Key, Body };
try {
  const parallelUploads3 = new Upload({
    client: new S3({}) || new S3Client({}),
    tags: [...], // optional tags
    queueSize: 4, // optional concurrency configuration
    partSize: 5MB, // optional size of each part
    leavePartsOnError: false, // optional manually handle dropped parts
    params: target,
  });

  parallelUploads3.on("httpUploadProgress", (progress) => {
    console.log(progress);
  });

  await parallelUploads3.done();
} catch (e) {
  console.log(e);
}
Run Code Online (Sandbox Code Playgroud)

来源:https://github.com/aws/aws-sdk-js-v3/blob/main/lib/lib-storage/README.md

  • 由于某种原因,我的应用程序的内存只会通过这种方法增加。我找不到如何以良好且高效的方式使用 v3。 (3认同)

小智 5

这是我想出的方法,使用适用于 Nodejs 和 TypeScript 的 aws-sdk v3 来上传 Buffer 作为分段上传。

错误处理仍然需要一些工作(您可能希望在出现错误时中止/重试),但这应该是一个很好的起点...我已经使用高达 15MB 的 XML 文件对此进行了测试,到目前为止一切顺利。但没有任何保证!;)

import {
  CompleteMultipartUploadCommand,
  CompleteMultipartUploadCommandInput,
  CreateMultipartUploadCommand,
  CreateMultipartUploadCommandInput,
  S3Client,
  UploadPartCommand,
  UploadPartCommandInput
} from '@aws-sdk/client-s3'

const client = new S3Client({ region: 'us-west-2' })

export const uploadMultiPartObject = async (file: Buffer, createParams: CreateMultipartUploadCommandInput): Promise<void> => {
  try {
    const createUploadResponse = await client.send(
      new CreateMultipartUploadCommand(createParams)
    )
    const { Bucket, Key } = createParams
    const { UploadId } = createUploadResponse
    console.log('Upload initiated. Upload ID: ', UploadId)

    // 5MB is the minimum part size
    // Last part can be any size (no min.)
    // Single part is treated as last part (no min.)
    const partSize = (1024 * 1024) * 5 // 5MB
    const fileSize = file.length
    const numParts = Math.ceil(fileSize / partSize)

    const uploadedParts = []
    let remainingBytes = fileSize

    for (let i = 1; i <= numParts; i ++) {
      let startOfPart = fileSize - remainingBytes
      let endOfPart = Math.min(partSize, startOfPart + remainingBytes)

      if (i > 1) {
        endOfPart = startOfPart + Math.min(partSize, remainingBytes)
        startOfPart += 1
      }

      const uploadParams: UploadPartCommandInput = {
        // add 1 to endOfPart due to slice end being non-inclusive
        Body: file.slice(startOfPart, endOfPart + 1),
        Bucket,
        Key,
        UploadId,
        PartNumber: i
      }
      const uploadPartResponse = await client.send(new UploadPartCommand(uploadParams))
      console.log(`Part #${i} uploaded. ETag: `, uploadPartResponse.ETag)

      remainingBytes -= Math.min(partSize, remainingBytes)

      // For each part upload, you must record the part number and the ETag value.
      // You must include these values in the subsequent request to complete the multipart upload.
      // https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html
      uploadedParts.push({ PartNumber: i, ETag: uploadPartResponse.ETag })
    }

    const completeParams: CompleteMultipartUploadCommandInput = {
      Bucket,
      Key,
      UploadId,
      MultipartUpload: {
        Parts: uploadedParts
      }
    }
    console.log('Completing upload...')
    const completeData = await client.send(new CompleteMultipartUploadCommand(completeParams))
    console.log('Upload complete: ', completeData.Key, '\n---')
  } catch(e) {
    throw e
  }
}

Run Code Online (Sandbox Code Playgroud)