2015-09-18 111 views
10

我需要更新所有AmazonS3云文件中的缓存控制标头。但是,我无法弄清楚我是如何使用jclouds API来做到的。 我使用的是Apache jclouds插件。我有两个相关的答案:如何更新现有Amazon S3文件的元数据?

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

回答

14

您不能:

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

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

+1

我找到了元数据的话题非常令人困惑的AWS文档 - 沿边链接您提供,我发现了另一个链接到他们的用户指南,其中显示了如何使用管理控制台添加或删除对象元数据。 唯一的解决这个矛盾,我可以想出,是当他们说:“你不能修改对象元数据”,他们的意思是,你不能修改特定的元数据项的值。你的想法是什么? http://docs.aws.amazon.com/AmazonS3/latest/UG/EditingtheMetadataofanObject.html – Israel

+0

或许他们的意思是你无法通过REST接口修改元数据,但你可以通过管理控制台? (在幕后它可能会克隆和删除)。 – kaifong

+0

见下面我的解决方案,您可以更新现有的S3对象,并在同一时间设置新的/更新的元数据。它与复制解决方案类似。 – robnick

13

有可能通过执行对象复制更改元数据(见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

谢谢丹,我最终做了同样的事情。 –

0

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

我的解决方案是用修改后的元数据更新现有的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);