如何使用 PHP API 将包含子文件夹和文件的文件夹复制/复制到 S3 存储桶中的另一个目录中?
$s3->copy_object
只复制文件夹,而不复制里面的文件和子文件夹。
我是否必须使用$s3->list_objects
来获取所有文件和目录并$s3->copy_object
在每个文件/目录上运行?
S3 不是文件系统,它是对象存储。文件夹实际上并不存在于任何有形的意义上。文件夹只是您可以称为共享前缀的东西。换句话说,如果你创建path/to/one
and path/to/two
,它也不会导致path
andpath/to
存在。如果您看到它们,那是因为某些组件获取了一个对象列表,将它们的键拆分为/
,并决定将该列表显示为层次结构。
您想“将一个文件夹复制到另一个文件夹中”。将其重新表述为 S3 术语,您希望“将具有相同前缀的所有对象复制到具有不同前缀的对象中”。这么说使方法变得清晰:获取带有一个前缀的对象列表,然后复制它们中的每一个。
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")
这是从亚马逊获取的一些代码。此代码将项目 a 三次复制到目标,您需要做的是更改它,以便它循环遍历每个键并将其添加到批处理中。
<?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();
}
一种方法是使用列表对象并逐个移动每个对象。另一种方法是使用 s3fuse,它将您的 s3 存储桶作为本地目录,然后您可以应用简单的命令(如“mv”)来移动文件。
对于那些使用 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));
}
}
}
使用@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)
}
}