dev7
dev7

Reputation: 6369

Uploading multiple files to AWS S3 with Progress Bar

I'm using Laravel to upload multiple files into an S3 bucket but can't get the progress data correctly on client side.

On client side I have the following (simplified):

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);
}

On Laravel's side:

$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');
   } 

This works great as far as uploading the files to the S3 bucket.

The problem is that when uploading multiple files, the client side updateProgress function is only called once and only when all files have been uploaded (instead of after each file and during the uploads).

Ideally, the progress bar will get updated periodically during file uploads, so that when uploading large files, it will show close to real time progress (and not just when each file is completed).

How would I get Laravel (or PHP in general) to report back the progress, during the uploads?

Upvotes: 0

Views: 2115

Answers (1)

onin
onin

Reputation: 5760

Here's how to do it in 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
            );
        }
    ]
]);

This is explained in the AWS docs - S3 Config section. It works by exposing GuzzleHttp's progress property-callable, as explained in this SO answer.

I understand you're doing it a bit differently (with Streams) but I'm sure you can adjust my example to your needs.

Upvotes: 1

Related Questions