使用AWS PHP SDK 3.x时,是否可以使用getCommand数组将多部分文件并行批量上传到S3?

问题描述

我正在一个将大量文件上传到S3的过程中,对于较小的文件,我正在使用getCommand构建一个命令列表以同时上传它们,如下所示:

$commands = array();
$commands[] = $s3Client->getCommand('PutObject',array(
    'Bucket' => 'mybucket','Key'    => 'filename.ext','Body'   => fopen('filepath','r'),));
$commands[] = $s3Client->getCommand('PutObject','Key'    => 'filename_2.ext','Body'   => fopen('filepath_2',));
etc.

try {
    $pool = new CommandPool($s3Client,$commands,[
        'concurrency' => 5,'before' => function (CommandInterface $cmd,$iterKey) {
            //Do stuff before the file starts to upload
        },'fulfilled' => function (ResultInterface $result,$iterKey,PromiseInterface $aggregatePromise) {
            //Do stuff after the file is finished uploading
        },'rejected' => function (AwsException $reason,PromiseInterface $aggregatePromise) {
            //Do stuff if the file fails to upload
        },]);

    // Initiate the pool transfers
    $promise = $pool->promise();

    // Force the pool to complete synchronously
    $promise->wait();

    $promise->then(function() { echo "All the files have finished uploading!"; });
} catch (Exception $e) {
    echo "Exception Thrown: Failed to upload: ".$e->getMessage()."<br>\n";
}

这对于较小的文件来说效果很好,但是我的一些文件足够大,我希望它们可以自动上传为多个部分。因此,我不想使用上传整个文件getCommand('PutObject'),而是想使用getCommand('ObjectUploader')之类的东西,以便可以根据需要自动分解较大的文件。但是,当我尝试使用getCommand('ObjectUploader')时会抛出错误,并说它不知道该怎么做。我猜想该命令的名称可能不同,这就是为什么它会引发错误。但是,也有可能无法做到这一点。

如果您过去曾从事过类似的工作,您是如何做到的?甚至即使您还没有进行任何工作,我也会接受您可能有的任何想法。

谢谢!

参考: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_commands.html#command-pool https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-multipart-upload.html#object-uploader

解决方法

我决定朝这个方向发展,而不是使用并发命令数组,我现在使用一组并发的MultipartUploader承诺,如本页示例所示:https://500.keboola.com/parallel-multipart-uploads-to-s3-in-php-61ff03ffc043

以下是基本知识:

//Create an array of your file paths
$files = ['file1','file2',...];

//Create an array to hold the promises
$promises = [];

//Create MultipartUploader objects,and add them to the promises array
foreach($files as $filePath) {
  $uploader = new \Aws\S3\MultipartUploader($s3Client,$filePath,$uploaderOptions);
  $promises[$filePath] = $uploader->promise();
}

//Process the promises once they are all complete
$results = \GuzzleHttp\Promise\unwrap($promises);