4

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?

turntwo
  • 2,452
  • 19
  • 28
  • PhP (server-side) progress bar no. However... have you tried this one? http://www.w3bees.com/2013/12/multiple-file-upload-with-progress-bar.html It needs php & Javascript. Otherwise you cannot do a progress bar at all =) – Marco Mura Nov 21 '14 at 09:29
  • 1
    Yeah, of course there has to be javascript involved to even display the progress bar, that I left out. The problem with ajaxForm.uploadProgress is that it won't detect the progress of an S3 upload. This is what I initially had, but because the files are already in the server the progress bar is immediately at 100% and then loads for a few seconds while the actual S3 upload is ongoing which is clearly not what I want. – turntwo Nov 21 '14 at 09:33

2 Answers2

3

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.

Community
  • 1
  • 1
The Onin
  • 5,068
  • 2
  • 38
  • 55
0

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.

Community
  • 1
  • 1
turntwo
  • 2,452
  • 19
  • 28
  • 1
    I'm into the same mess as you. Client wants a progress bar. It's working if I upload directly JS->S3 (js sdk) but credentials are plain-text. Not good of course. Now I have it working JS->PHP->S3 using putObject but have no clue about how to get any progress info back? Did not find anything except many questions/answers like this one with no final solution examples :D Do you have any clues as to how to actually get progress info? Will I NEED to use sessions? Because that's not a good idea for my environment ... – trainoasis Aug 25 '16 at 10:18