【问题标题】:Amazon S3 copy the directory to another directoryAmazon S3 将目录复制到另一个目录
【发布时间】:2012-09-13 04:01:20
【问题描述】:

如何使用 PHP API 将包含子文件夹和文件的文件夹复制/复制到 S3 存储桶内的另一个目录中?

$s3->copy_object只复制文件夹,不复制里面的文件和子文件夹。

我是否必须使用$s3->list_objects 来获取所有文件和目录并在每个文件/目录上运行$s3->copy_object

【问题讨论】:

  • +1 表示问题。人们可能理解也可能不理解资源路径 S3 的概念,但请求是完全有效的。也许问题是 S3 是否支持在内部复制资源(或为同一资源创建多个路径,为什么不支持?)以某种方式?如果有很多文件,必须全部下载并重新上传真的很荒谬......

标签: amazon-s3 directory amazon move


【解决方案1】:

使用@aws-sdk/client-s3,这里是完整的js代码:

import {
    S3Client,
    CopyObjectCommandInput,
    CopyObjectCommand,
    ListObjectsCommandInput,
    ListObjectsCommand
} from '@aws-sdk/client-s3';
  
const s3Client = new S3Client({ region: 'us-east-1' });

const listS3Objects = async (input: ListObjectsCommandInput) => {
     const command = new ListObjectsCommand(input);
     return await s3Client.send(command);
}

const copyS3Object = async (input: any) => {
    const command = new CopyObjectCommand(input);
    return await s3Client.send(command);
};

export const copyFolder = async (fromBucket:string, fromFolderKey:string, toBucket:string, toFolderKey: any) => {
      
try {
    const listObjectsResponse = await listS3Objects({
        Bucket: fromBucket,
        Prefix: `${fromFolderKey}/`
    })

    const fromObjectKeys = listObjectsResponse.Contents.map(content => content.Key)

    for (let fromObjectKey of fromObjectKeys) {
        const toObjectKey = fromObjectKey.replace(fromFolderKey, toFolderKey);

       await copyS3Object({
          Bucket: toBucket,
          CopySource: `${fromBucket}/${fromObjectKey}`,
          Key: toObjectKey,
       })
    }
  } catch (error) {
     throw new Error(error)
  }
}

【讨论】:

    【解决方案2】:

    对于那些寻找使用 aws sdk 的 java 解决方案的人:

    public static void copyAllFilesWithPrefix(AmazonS3 s3Client,
                                              String srcBucket,
                                              String srcPrefix,
                                              String destBucket,
                                              String destPrefix) {
        ObjectListing objectListing = s3Client.listObjects(srcBucket, srcPrefix);
        for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
            S3Object srcFile = s3Client.getObject(srcBucket, objectSummary.getKey());
            String destKey = srcFile.getKey().replace(srcPrefix, destPrefix);
            if (!s3Client.doesObjectExist(destBucket, destKey)) {
                copyFile(s3Client, srcFile, destBucket, srcFile.getKey().replace(srcPrefix, destPrefix));
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      scala 代码(在一个存储桶中的文件夹之间复制):

      def copyFolders(bucketName: String, srcFolder: String, targetFolder: String): Unit = {
      import scala.collection.JavaConversions._
      val transferManager: TransferManager = TransferManagerBuilder.standard.build
      try {
      
        for (file <- s3.listObjects(bucketName, s"$srcFolder/").getObjectSummaries) {
          val fileName = file.getKey.replace(s"$srcFolder/", "")
          if (!fileName.isEmpty) {
            val transferProcess: Copy = transferManager.copy(bucketName, file.getKey,
              bucketName, s"$targetFolder/$fileName")
            log.info(s"Old key = ${file.getKey}")
            log.info(s"New file Key = $targetFolder/$fileName")
            transferProcess.waitForCompletion()
          }
        }
      } catch {
        case e: AmazonServiceException =>
          log.error(e.getErrorMessage, e)
          System.exit(1)
        case e: AmazonClientException =>
          log.error("Amazon client error: " + e.getMessage, e)
          System.exit(1)
        case e: InterruptedException =>
          log.error("Transfer interrupted: " + e.getMessage, e)
          System.exit(1)
      }
      }
      

      用法:

      copyFolders("mybucket", "somefolder/srcfolder", "somefolder/targetfolder")
      

      【讨论】:

        【解决方案4】:

        这里有一些直接取自亚马逊的代码。此代码将项目 a 复制到目标 3 次,您需要做的是更改它,以便循环遍历每个键并将其添加到批处理中。

        <?php
        
        // Include the AWS SDK using the Composer autoloader.
        require 'vendor/autoload.php';
        
        use Aws\S3\S3Client;
        
        $sourceBucket = '*** Your Source Bucket Name ***';
        $sourceKeyname = '*** Your Source Object Key ***';
        $targetBucket = '*** Your Target Bucket Name ***';
        
        // Instantiate the client.
        $s3 = S3Client::factory();
        
        // Copy an object.
        $s3->copyObject(array(
            'Bucket'     => $targetBucket,
            'Key'        => "{$sourceKeyname}-copy",
            'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
        ));
        
        // Perform a batch of CopyObject operations.
        $batch = array();
        for ($i = 1; $i <= 3; $i++) {
            $batch[] = $s3->getCommand('CopyObject', array(
                'Bucket'     => $targetBucket,
                'Key'        => "{$sourceKeyname}-copy-{$i}",
                'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
            ));
        }
        try {
            $successful = $s3->execute($batch);
            $failed = array();
        } catch (\Guzzle\Service\Exception\CommandTransferException $e) {
            $successful = $e->getSuccessfulCommands();
            $failed = $e->getFailedCommands();
        }
        

        【讨论】:

          【解决方案5】:

          S3 不是一个文件系统,它是一个对象存储。文件夹实际上并不存在于任何有形的意义上。文件夹只是您可以称为共享前缀的东西。换句话说,如果您创建path/to/onepath/to/two,它也不会导致pathpath/to 存在。如果您看到它们,那是因为某些组件获取了一个对象列表,在 / 上拆分了它们的键,并决定将该列表显示为层次结构。

          您想“将一个文件夹复制到另一个文件夹中”。将其重新表述为 S3 术语,您希望“将具有相同前缀的所有对象复制到具有不同前缀的对象中”。这么说就清楚了方法:获取带有一个前缀的对象列表,然后复制它们中的每一个。

          【讨论】:

          • 然而 aws s3 cp -R 设法在一个命令中完成它
          【解决方案6】:

          一种方法是使用列表对象并逐个移动每个对象。另一种方法是使用 s3fuse,它将您的 s3 存储桶作为本地目录,然后您可以应用简单的命令(如“mv”)来移动文件。

          【讨论】:

            猜你喜欢
            • 2018-05-22
            • 2014-07-18
            • 2013-01-11
            • 1970-01-01
            • 1970-01-01
            • 2011-09-07
            • 2017-11-18
            • 2012-02-15
            • 1970-01-01
            相关资源
            最近更新 更多