7

I am migrating my code from AWS PHP SDK1 to SDK2 (https://github.com/aws/aws-sdk-php).

I have an image uploader. In my previous version, I would specify the Content-Type of my image like so:

$response = $this->s3->create_object(
                $bucket,
                $key,
                array(
                    'fileUpload'=>$file_resource,
                    'contentType'=>$mime, 
                    'acl' => AmazonS3::ACL_PUBLIC,
                    )
                );

This is my new version:

$response = $this->s3->upload(
                    $bucket, 
                    $key, 
                    $file_resource, 
                    'public-read',
                    array('params' => array('Metadata' => array('ContentType'=>$mime)))
                    );

I've tried different spellings of ContentType, in the S3 site it modifies the name to look like 'x-amz-meta-contenttype', while the value of 'Content-Type' is the default 'binary/octet-stream'.

I've also tried using the EntityBody feature, but same results:

$response = $this->s3->upload(
                    $this->bucket, 
                    $to, 
                    EntityBody::factory($file_resource), 
                    'public-read',
                    array('params' => array('Metadata' => array('ContentType'=>$mime)))
                    );

How do I set the content-type in this new API?

EDIT: I see somewhere in the documentation:

The AWS SDK for PHP will attempt to automatically determine the most appropriate Content-Type header used to store the object. If you are using a less common file extension and your Content-Type header is not added automatically, you can add a Content-Type header by passing a ContentType option to the operation.

First off, I am uploading simple images, yet according to my S3 dashboard, they are uploaded as 'binary/octet-stream'. About their second point, I've tried many combinations of arrays with 'ContentType' I'm not sure why it's not working...

Nathan H
  • 48,033
  • 60
  • 165
  • 247

3 Answers3

18

At the end, this set of options worked:

array('params' => array('ContentType' => $mime))

No need for Metadata

Nathan H
  • 48,033
  • 60
  • 165
  • 247
4
  1. Well, using AWS\S3\S3Client::putObject() directly would definitely give you the control you need.

  2. File extensions need to be lowercase for the automatic detection to work.

  3. You can find the list of supported mime types in Guzzle\Http\Mimetypes.

Ryan Parman
  • 6,855
  • 1
  • 29
  • 43
  • 1) From what I understand, upload() uses putObject behind the scenes, and is the recommended solution for file uploads. 2) Is it the file extension of the source, or of the destination name? My destination are lowercase, and the source are from PHP's temporary location for uploads - which I think have no extensions. 3) As expected, most image extensions are in that list. – Nathan H Feb 20 '14 at 09:44
  • 1
    The "source" file is `$_FILES["avatar-file"]["tmp_name"]`, using PHP's handling of uploaded files. Correct me if I am wrong, but I believe the temp names generated by PHP do not keep the file extension... – Nathan H Feb 20 '14 at 09:49
  • 3
    I personally use `finfo(FILEINFO_MIME_TYPE)` to detect mime type, which I used to pass on to the AWS SDK. Worked fine until I switched to the new SDK. – Nathan H Feb 20 '14 at 09:58
  • It's a really strange. Works fine with aws-sdk-php-3.19.8, ubuntu 14.04. php-5.5.9 – ALex_hha Sep 28 '16 at 13:05
3

I believe the more recent AWS API versions require that the content type be set directly, e.g.

$client->putObject([
       'Bucket'      => $sBucket,
       'Key'         => $sPath,
       'SourceFile'  => $sData,
       'ContentType' => $sMimeType]);
CharlieH
  • 1,432
  • 2
  • 12
  • 19