Amazon S3 копирует каталог в другой каталог
Как копировать/дублировать папку, содержащую подпапки и файлы, в другой каталог в ведре S3 с использованием PHP API?
$s3->copy_object
копирует только папку, но не файлы и подпапки внутри.
Нужно ли использовать $s3->list_objects
для получения всех файлов и каталогов и запускать $s3->copy_object
в каждом файле/каталоге?
Ответы
Ответ 1
S3 не является файловой системой, это хранилище объектов. Папки на самом деле не существуют в каком-либо ощутимом смысле; папка - это то, что вы можете назвать общим префиксом. Иными словами, если вы создаете path/to/one
и path/to/two
, это также не означает существование path
и path/to
. Если вы их видите, то, потому что какой-то компонент взял список объектов, разделил их ключи на /
и решил отобразить этот список как иерархию.
Вы хотите "скопировать папку в другую папку". Перефразируя это в терминах S3, вы хотите "дублировать все объекты с одним и тем же префиксом на объекты с другим префиксом". Сказав это, метод очистится: получите список объектов с одним префиксом, затем скопируйте каждый из них.
Ответ 2
Один из способов сделать это - использовать объекты списка и перемещать каждый объект по одному. Другой способ - использовать s3fuse, который сделает ваш ведро s3 в качестве локального каталога, а затем вы можете просто применить простую команду, например "mv", чтобы переместить файлы.
Ответ 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();
}
Ответ 4
Код для 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")