Aws-sdk-php: Is MetaData ignored in Aws\S3\S3Client::putObject() ?

Created on 6 Aug 2015  路  8Comments  路  Source: aws/aws-sdk-php

$s3->putObject([
    'Bucket'=>$bucket,
    'Key'=>$key,
    'Body'=>$body,
    'CacheControl'=>'max-age=172800',
    'MetaData'=>[
        'Content-Type'=>$mime
    ]
]);

Object always show up with application/octet-stream instead of the correct values.

guidance

Most helpful comment

You should be using the ContentType parameter, not MetaData for this, as documented in the V2 and V3 API reference for PutObject. Example:

$s3->putObject([
    'Bucket'=>$bucket,
    'Key'=>$key,
    'Body'=>$body,
    'CacheControl'=>'max-age=172800',
    'ContentType'=>$mime
]);

All 8 comments

You should be using the ContentType parameter, not MetaData for this, as documented in the V2 and V3 API reference for PutObject. Example:

$s3->putObject([
    'Bucket'=>$bucket,
    'Key'=>$key,
    'Body'=>$body,
    'CacheControl'=>'max-age=172800',
    'ContentType'=>$mime
]);

@jeremeamia It is still not working. We are doing exactly as you directed, but no change. We are serve the files through cloudfront, but they show up as file downloads to the client instead of showing them in browser.

@r3wt Can you share the code that isn't working? If I execute the following:

$firstVersion = $s3->putObject([
    'Bucket' => <my-bucket>,
    'Key' => 'response.xml',
    'Body' => fopen(__DIR__ . '/response.xml', 'r'),
    'ContentType' => 'application/xml',
]);

then responses to a GetObject operation come back with a header of Content-Type: application/xml.

$s3->putObject([
    'Bucket'=>$bucket,
    'Key'=>$key,
    'Body'=>$body,
    'CacheControl'=>'max-age=172800',
    'Content-Type'=>$mime
]);

where $bucket is the target bucket, $key is a string, $body is a blob, and $mime is one of following possible types:

image/png
image/jpeg
image/gif

When accessing image directly, the browser prompts for a file download. this is not a desired behavior.

The content type should be provided to putObject as ContentType, not Content-Type. Does making that change fix the issue?

@jeskew i can make the change, but what can i do about images that are uploaded already? we have around 10k files uploaded already. I wish php was strictly typed, and you could define the shape of arrays. it would make it so much better. Also Content-Type is a standard header. why did you remove the hyphen? random deviations from accepted protocols are a bad practice.

To change the metadata on an object in S3, you'll need to copy the object over itself and pass in a MetadataDirective of REPLACE. This script would replace the content type on a single object:

use PHPUnit_Framework_Assert as Assert;

$s3 = new \Aws\S3\S3Client([
    'region' => '<region>',
    'version' => 'latest',
]);
$bucket = '<bucket>';
$key = '<key>';

$s3->copyObject([
    'Bucket' => $bucket,
    'Key' => $key,
    'CopySource' => "$bucket/$key",
    'ContentType' => 'image/png',
    'MetadataDirective' => 'REPLACE',
]);

$metadata = $s3->headObject([
    'Bucket' => $bucket,
    'Key' => $key,
]);

Assert::assertEquals('image/png', $metadata['ContentType']);

@jeskew I'm glad I found your answer here because the doc is not clear about that.

It's so confusing :

  • There is a Metadata, a ContentType and a MetadataDirective field
  • If I only pass a ContentType nothing appends.. Not even an error
  • Even I don't pass Metadata, I have to pass MetadataDirective in order to update ContentType
  • ContentType update does not have the same behaviour as other header (eg ContentEncoding)

PS: I've submitted an issue about JavaScript API documentation : https://github.com/aws/aws-sdk-js/issues/1092

Was this page helpful?
0 / 5 - 0 ratings