How do I update metadata for an existing Amazon S3

2020-02-26 14:42发布

I need to update the cache control header in all AmazonS3's Cloud Files. However, I can't figure out how I do that using the jclouds API. I'm using apache jclouds plugin. And I got two related answers:

The first answer is suggesting to use SwiftKey Api class which is not available in grails's jcloud plugin. The second answer is using AWS java sdk for which there is already a grails wrapping plugin https://grails.org/plugin/aws-sdk but it doesn't support metadata update.

5条回答
男人必须洒脱
2楼-- · 2020-02-26 14:48

As at March 2018, the latest version of the AWS SDK for .NET Core has changed. It now uses asynchronous programming. Many of the method signatures have changed. While you still cannot change metadata without the object copy solution that Dan has suggested, the code to do so has.

My solution is to update the existing S3 object with the modified metadata.

The following works for me to update a single metadata value (based on key and new value). I've got two loops for setting the metadata but it could be optimised to just have one:

string fileContents = string.Empty;
Dictionary<string, string> fileMetaData = null;

GetObjectRequest request = new GetObjectRequest
{
  BucketName = bucketName,
  Key = setKeyName
};

var response = await s3Client.GetObjectAsync(request);

// Read the contents of the file
using (var stream = response.ResponseStream)
{
  // Get file contents
  TextReader tr = new StreamReader(stream);
  fileContents = tr.ReadToEnd();
}

// Create the File Metadata collection
fileMetaData = new Dictionary<string, string>();
foreach (string metadataKey in response.Metadata.Keys)
{
  fileMetaData.Add(metadataKey, response.Metadata[metadataKey]);
}

// Update the metadata value (key to update, new value)
fileMetaData[metaDataKeyToUpdate] = metaDataNewValue;

// Update the existing S3 object    
PutObjectRequest putRequest1 = new PutObjectRequest
{
  BucketName = bucketName,
  Key = setKeyName,
  ContentBody = fileContents
};

// Set the metadata
foreach (string metadataKey in response.Metadata.Keys)
{
  putRequest1.Metadata.Add(metadataKey, fileMetaData[metadataKey]);
}

PutObjectResponse response1 = await s3Client.PutObjectAsync(putRequest1);
查看更多
Fickle 薄情
3楼-- · 2020-02-26 14:56

It is possible to change the metadata by performing an object copy (see How to update metadata using Amazon S3 SDK):

ObjectMetadata metadataCopy = new ObjectMetadata();
// copy previous metadata
metadataCopy.addUserMetadata("newmetadata", "newmetadatavalue");

CopyObjectRequest request = new CopyObjectRequest(bucketName, existingKey, bucketName, existingKey)
      .withNewObjectMetadata(metadataCopy);

amazonS3Client.copyObject(request);

Whether this is philosophically an "update" is up to you to decide.

查看更多
smile是对你的礼貌
4楼-- · 2020-02-26 15:06

You can't:

Each Amazon S3 object has data, a key, and metadata. Object key (or key name) uniquely identifies the object in a bucket. Object metadata is a set of name-value pairs. You can set object metadata at the time you upload it. After you upload the object, you cannot modify object metadata. The only way to modify object metadata is to make a copy of the object and set the metadata.

http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html

查看更多
放荡不羁爱自由
5楼-- · 2020-02-26 15:08

In my case, I care about the object versions, and copying creates a new version. I decided to create a parallel, "hidden" object with the mutable metadata. For example, if I have /foo/bar/baz, then I would create /foo/bar/.baz.

查看更多
爷的心禁止访问
6楼-- · 2020-02-26 15:09

PHP Example

I understand this question was not PHP specific, but it may help someone as it is a top result on Google.

This will overwrite the existing object.

$client = new \Aws\S3\S3Client([
    'version' => '2006-03-01',
    'region' => 'BUCKET-REGION'
]);

$updateResponse = $client->copyObject([
    'Key' => 'OBJECTKEY',
    'Bucket' =>  'MYBUCKET',
    'CopySource' => 'MYBUCKET/OBJECTKEY',
    'MetadataDirective' => 'REPLACE',
    'Metadata' => [
        'width' => 441,
        'height' => 189
    ]
]);

The Content Type was an existing metadata item

查看更多
登录 后发表回答