Voici une solution batch complète qui copie des fichiers d'un dossier à un autre en utilisant un seul appel de CommandPool::batch, bien que sous-jacent il exécute une commande executeAsync pour chaque fichier, donc je ne suis pas sûr que cela compte comme un seul appel API.
D'après ce que je comprends, vous devriez être capable de copier des centaines de milliers de fichiers en utilisant cette méthode car il n'y a pas de moyen d'envoyer un lot à AWS pour qu'il soit traité là-bas, mais si vous hébergez ceci sur une instance AWS ou même si vous l'exécutez sur Lambda, alors c'est "techniquement" traité chez AWS.
Installez le SDK :
composer require aws/aws-sdk-php
use Aws\ResultInterface;
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
use Aws\S3\Exception\DeleteMultipleObjectsException;
$bucket = 'nom-de-mon-bucket';
// Configurez vos identifiants dans le dossier .aws
// Voir : https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials_profiles.html
$s3 = new S3Client([
'profile' => 'default',
'region' => 'us-east-2',
'version' => 'latest'
]);
// Obtenez tous les fichiers dans S3
$files = array();
try {
$results = $s3->getPaginator('ListObjects', [
'Bucket' => $bucket,
'Prefix' => 'dossier-existant' // Dossier dans le bucket, ou supprimez ceci pour obtenir tous les fichiers dans le bucket
]);
foreach ($results as $result) {
foreach ($result['Contents'] as $object) {
$files[] = $object['Key'];
}
}
} catch (AwsException $e) {
error_log($e->getMessage());
}
if(count($files) > 0){
// Effectuer un lot d'opérations de Copie d'objet.
$batch = [];
foreach ($files as $file) {
$batch[] = $s3->getCommand('CopyObject', array(
'Bucket' => $bucket,
'Key' => str_replace('dossier-existant/', 'nouveau-dossier/', $file),
'CopySource' => $bucket . '/' . $file,
));
}
try {
$results = CommandPool::batch($s3, $batch);
// Vérifiez si tous les fichiers ont été copiés afin de supprimer en toute sécurité l'ancien répertoire
$count = 0;
foreach($results as $result) {
if ($result instanceof ResultInterface) {
$count++;
}
if ($result instanceof AwsException) {
}
}
if($count === count($files)){
// Supprimer l'ancien répertoire
try {
$s3->deleteMatchingObjects(
$bucket, // Bucket
'dossier-existant' // Préfixe, dossier dans le bucket, comme indiqué ci-dessus
);
} catch (DeleteMultipleObjectsException $exception) {
return false;
}
return true;
}
return false;
} catch (AwsException $e) {
return $e->getMessage();
}
}