Amazon S3 将目录复制到另一个目录
Posted
技术标签:
【中文标题】Amazon S3 将目录复制到另一个目录【英文标题】:Amazon S3 copy the directory to another directory 【发布时间】:2012-09-13 04:01:20 【问题描述】:如何使用 php API 将包含子文件夹和文件的文件夹复制/复制到 S3 存储桶内的另一个目录中?
$s3->copy_object
只复制文件夹,不复制里面的文件和子文件夹。
我是否必须使用$s3->list_objects
来获取所有文件和目录并在每个文件/目录上运行$s3->copy_object
?
【问题讨论】:
+1 表示问题。人们可能理解也可能不理解资源路径 S3 的概念,但请求是完全有效的。也许问题是 S3 是否支持在内部复制资源(或为同一资源创建多个路径,为什么不支持?)以某种方式?如果有很多文件,必须全部下载并重新上传真的很荒谬...... 【参考方案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/one
和path/to/two
,它也不会导致path
和path/to
存在。如果您看到它们,那是因为某些组件获取了一个对象列表,在 /
上拆分了它们的键,并决定将该列表显示为层次结构。
您想“将一个文件夹复制到另一个文件夹中”。将其重新表述为 S3 术语,您希望“将具有相同前缀的所有对象复制到具有不同前缀的对象中”。这么说就清楚了方法:获取带有一个前缀的对象列表,然后复制它们中的每一个。
【讨论】:
然而aws s3 cp -R
设法在一个命令中完成它【参考方案6】:
一种方法是使用列表对象并逐个移动每个对象。另一种方法是使用 s3fuse,它将您的 s3 存储桶作为本地目录,然后您可以应用简单的命令(如“mv”)来移动文件。
【讨论】:
以上是关于Amazon S3 将目录复制到另一个目录的主要内容,如果未能解决你的问题,请参考以下文章
如何使用适用于 Node.js 的 AWS 开发工具包将 Amazon S3 中的所有对象从一个前缀复制/移动到另一个前缀
如何将文件从 S3 复制到 Amazon EMR HDFS?
将数据从 Amazon S3 复制到 Redshift 并避免重复行