如何更新现有Amazon S3文件的元数据?

时间:2015-09-18 07:50:55

标签: java grails amazon-web-services amazon-s3 jclouds

我需要更新所有AmazonS3的云文件中的缓存控制标头。但是,我无法弄清楚如何使用jclouds API执行此操作。 我正在使用apache jclouds插件。我得到了两个相关的答案:

第一个答案是建议使用SwiftKey Api类,这在Grails的jcloud插件中是不可用的。第二个答案是使用AWS java sdk已经有一个grails包装插件https://grails.org/plugin/aws-sdk,但它不支持元数据更新。

6 个答案:

答案 0 :(得分:28)

可以通过执行对象复制来更改元数据(请参阅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);

这是否在哲学上是一个“更新”由你来决定。

答案 1 :(得分:20)

你不能:

  

每个Amazon S3对象都有数据,密钥和元数据。对象键(或   key name)唯一标识存储桶中的对象。对象元数据   是一组名称 - 值对。您可以在此时设置对象元数据   你上传它。 上传对象后,无法修改对象   元数据。修改对象元数据的唯一方法是制作副本   对象并设置元数据。

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

答案 2 :(得分:0)

PHP示例

我知道这个问题不是PHP特有的,但它可能对某人有帮助,因为它在Google上排名第一。

这将覆盖现有对象。

update()

The Content Type was an existing metadata item

答案 3 :(得分:0)

就我而言,我关心对象的版本,复制会创建一个新版本。我决定使用可变的元数据创建一个并行的“隐藏”对象。例如,如果我有/foo/bar/baz,那么我将创建/foo/bar/.baz

答案 4 :(得分:0)

如其他答案所述,可以发出“复制”请求,覆盖现有记录。

Ruby 示例

s3_client.copy_object({
  bucket: BUCKET, # Destination
  key: KEY, # Destination
  copy_source: "/#{BUCKET}/#{KEY}", # Source
  content_type: "text/html; charset=utf8", # Metadata update
  metadata_directive: "REPLACE"
})

答案 5 :(得分:-1)

截至2018年3月,最新版本的AWS SDK for .NET Core已更改。它现在使用异步编程。许多方法签名已经改变。虽然如果没有Dan建议的对象复制解决方案仍然无法更改元数据,那么这样做的代码就有了。

我的解决方案是使用修改后的元数据更新现有S3对象。

以下内容适用于我更新单个元数据值(基于键值和新值)。我有两个用于设置元数据的循环,但它可以优化为只有一个:

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);