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")