使用Progress Bar将多个文件上载到AWS S3

时间:2016-06-16 05:15:37

标签: php laravel file-upload amazon-s3 progress-bar

我使用Laravel将多个文件上传到S3存储桶但无法在客户端正确获取进度数据。

在客户端,我有以下(简化):

var xhr = new XMLHttpRequest();
xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", transferComplete, false);
xhr.open("POST", "my_url_to_upload");
xhr.send(formData);//formData is defined earlier and contains multiple files

function updateProgress(e) {
   console.log('updateProgress', e);
}

function transferComplete(e) {
   console.log("Files uploaded successfully.", e);
}

在Laravel的一面:

$files  = \Input::file('file');
$s3     = \Storage::disk('s3');
foreach ($files as $file)
   {
     $file_name = "/some_folder/" . $file->getClientOriginalName();
     $s3->put($file_name, file_get_contents($file), 'public');
   } 

就将文件上传到S3存储桶而言,这非常有用。

问题在于,当上传多个文件时,客户端updateProgress功能只会被调用一次,并且仅在所有文件上传后(而不是在每个文件之后和上传期间)。

理想情况下,进度条会在文件上传期间定期更新,因此在上传大文件时,它会显示接近实时的进度(而不仅仅是每个文件的完成时间)。

在上传过程中,我如何让Laravel(或一般的PHP)报告进度?

1 个答案:

答案 0 :(得分:1)

以下是如何在SDK v3中执行此操作:

$client = new S3Client(/* config */);

$result = $client->putObject([
    'Bucket'     => 'bucket-name',
    'Key'        => 'bucket-name/file.ext',
    'SourceFile' => 'local-file.ext',
    'ContentType' => 'application/pdf',
    '@http' => [
        'progress' => function ($downloadTotalSize, $downloadSizeSoFar, $uploadTotalSize, $uploadSizeSoFar) {
            printf(
                "%s of %s downloaded, %s of %s uploaded.\n",
                $downloadSizeSoFar,
                $downloadTotalSize,
                $uploadSizeSoFar,
                $uploadTotalSize
            );
        }
    ]
]);

AWS文档中解释了这一点 - S3 Config section。它的工作原理是暴露GuzzleHttp的progress属性可调用,如this SO answer中所述。

我理解你的做法有点不同(使用Streams),但我确信你可以根据自己的需要调整我的示例。