turntwo
turntwo

Reputation: 2520

AWS S3 PHP Progress Bar (Server to Cloud)

I have an image upload system in my application written in PHP. The file browser opens, user picks an image, I upload it to my server, I crop, I resize, I apply a watermark to it. Bottom line is the images are in my server. At some point, the user clicks a button and then I move those files to my S3 bucket. Naturally, I need a progress bar because, ze client wants a progress bar.

Now uploading the files is quite easy:

    $result = $this->awsS3Client->putObject(array(
        'Bucket' => 'bad-dum-tss-bucket',
        'Key'    => $destinationFilePath,
        'SourceFile'  => $sourceFilePath,
        'ContentType' => $mimeType,
        'ACL'    => 'public-read',
    ));

I can even go multi-part

    $uploader = UploadBuilder::newInstance()
        ->setClient($this->awsS3Client)
        ->setSource($sourceFilePath)
        ->setBucket( 'bad-dum-tss-bucket')
        ->setKey($destinationFilePath)
        ->build();

    try {
        $uploader->upload();
    } catch (MultipartUploadException $e) {
        $uploader->abort();
    }

No problem there until I realize my client needs a freaking progress bar. Now I've searched a lot and all I can see are links to uploaders such as http://fineuploader.com/ that assumes that the upload will happen directly from the browser (i.e. not from my server). So PHP-progress bar-S3, anybody?

Upvotes: 4

Views: 1749

Answers (2)

onin
onin

Reputation: 5760

If you're still interested, I found a way to track progress in PHP with AWS 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.

Upvotes: 3

turntwo
turntwo

Reputation: 2520

I got this to work by firing concurrent XHRs to the server to poll the upload progress and saving it to a session variable. See: Why are my XHR calls waiting for each other to return a response where I asked another question related to XHR polling and session blocking in order to accomplish this.

In the end though, I decided to drop all of this altogether. My production server was an EC2 instance so any upload to the S3 server took only very little network overhead, (I should have realized this sooner). I could transfer a couple of MBs of images (all that I will ever need) in less than 3 seconds so I decided to just not display a progress bar as it doesn't justify the cost of adding nasty session calls in various parts of my code.

Upvotes: 0

Related Questions