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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32646646/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:54:12  来源:igfitidea点击:

How do I update metadata for an existing Amazon S3 file?

javagrailsamazon-web-servicesamazon-s3jclouds

提问by Priyanshu Chauhan

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:

我需要更新所有 AmazonS3 云文件中的缓存控制标头。但是,我不知道如何使用 jclouds API 做到这一点。我正在使用 apache jclouds 插件。我得到了两个相关的答案:

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-sdkbut it doesn't support metadata update.

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

采纳答案by Dan Gravell

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

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

这是否是哲学上的“更新”由您决定。

回答by E.J. Brennan

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.

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

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

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

回答by robnick

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.

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

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

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

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

回答by styks

PHP Example

PHP 示例

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

我知道这个问题不是特定于 PHP 的,但它可能对某人有所帮助,因为它是 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

内容类型是一个现有的元数据项

回答by John Lindal

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.

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