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

Java 如何更新现有AmazonS3文件的元数据?,java,grails,amazon-web-services,amazon-s3,jclouds,Java,Grails,Amazon Web Services,Amazon S3,Jclouds,我需要更新所有AmazonS3云文件中的缓存控制头。但是,我不知道如何使用jcloudsapi来实现这一点。 我正在使用ApacheJClouds插件。我得到了两个相关的答案: 第一个答案是建议使用SwiftKey Api类,这在grails的jcloud插件中是不可用的。第二个答案是使用AWS java sdk,它已经有一个grails包装插件,但不支持元数据更新。您不能: 每个AmazonS3对象都有数据、一个键和元数据。对象键(或 密钥名称)唯一标识存储桶中的对象。对象元数据 是一

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

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

您不能:

每个AmazonS3对象都有数据、一个键和元数据。对象键(或 密钥名称)唯一标识存储桶中的对象。对象元数据 是一组名称-值对。您可以同时设置对象元数据 你上传它上传对象后,无法修改对象 元数据。修改对象元数据的唯一方法是复制 对象并设置元数据。


可以通过执行对象复制来更改元数据(请参阅):


这在哲学上是否是“更新”取决于您的决定。

截至2018年3月,用于.NET Core的AWS SDK的最新版本已经更改。它现在使用异步编程。许多方法签名已更改。如果没有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);
string fileContents=string.Empty;
Dictionary fileMetaData=null;
GetObjectRequest=新的GetObjectRequest
{
BucketName=BucketName,
Key=setKeyName
};
var response=wait s3Client.GetObjectAsync(请求);
//读取文件的内容
使用(var stream=response.ResponseStream)
{
//获取文件内容
TextReader tr=新的StreamReader(stream);
fileContents=tr.ReadToEnd();
}
//创建文件元数据集合
fileMetaData=新字典();
foreach(响应中的字符串metadataKey.Metadata.Keys)
{
添加(metadataKey,response.Metadata[metadataKey]);
}
//更新元数据值(要更新的键,新值)
fileMetaData[metaDataKeyToUpdate]=metaDataNewValue;
//更新现有的S3对象
PutObjectRequest putRequest1=新的PutObjectRequest
{
BucketName=BucketName,
Key=setKeyName,
ContentBody=fileContents
};
//设置元数据
foreach(响应中的字符串metadataKey.Metadata.Keys)
{
putRequest1.Metadata.Add(metadataKey,fileMetaData[metadataKey]);
}
PutObjectResponse response1=等待s3Client.PutObjectAsync(putRequest1);

PHP示例

我知道这个问题并不是针对PHP的,但它可能会帮助一些人,因为这是Google上的一个顶级结果

这将覆盖现有对象

$client=new\Aws\S3\S3Client([
“版本”=>“2006-03-01”,
“区域”=>“桶区域”
]);
$updateResponse=$client->copyObject([
'Key'=>'OBJECTKEY',
“Bucket”=>“MYBUCKET”,
“CopySource”=>“MYBUCKET/OBJECTKEY”,
'MetadataDirective'=>'REPLACE',
“元数据”=>[
“宽度”=>441,
“高度”=>189
]
]);

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

,如其他答案中所述,可以提出一个覆盖现有记录的“复制”请求

Ruby示例
s3\u client.copy\u对象({
桶:桶,#目的地
钥匙:钥匙,#目的地
复制#u源:“/#{BUCKET}/#{KEY}”,#source
内容类型:“text/html;charset=utf8”,#元数据更新
元数据_指令:“替换”
})

我发现关于元数据主题的AWS文档非常混乱-除了您提供的链接之外,我还找到了另一个指向其用户指南的链接,其中显示了如何使用管理控制台添加或删除对象元数据。我能想到的解决这一冲突的唯一办法是,当他们说“您不能修改对象元数据”时,他们的意思是,您不能修改特定元数据键的值。你是怎么想的?也许这意味着您不能通过REST接口修改元数据,但可以通过管理控制台修改元数据?(在幕后可能会进行克隆和删除)。请参阅下面的解决方案,您可以更新现有的S3对象,同时设置新的/更新的元数据。它类似于复制解决方案。我意识到这是一个旧线程,但现在的文档中清楚地指出“此操作创建具有更新设置和上次修改日期的对象副本”。因此,对web控制台没有特殊处理。谢谢Dan,我最后也做了同样的事情。这将在客户端上下载整个文件,在内存中,所以只适用于非常有限的用例。是的,你是对的。被指控有罪!PST:对象复制就像所有的heck:)那个么对于你们上传到AWSS3的每个文件,你们都上传了第二个隐藏文件,里面嵌入了MD5?这不会增加你的看跌期权和看跌期权的成本吗?是的,但我的应用程序容量不高。谢谢。旁注:有趣的是,在java/ruby世界中,这个老问题仍然相关!OP适用于javascript框架,即使是2年前的问题也变得无关紧要。你能帮我更新laravel PHP中现有对象的元数据吗?我尝试过你的解决方案,但无法更新现有文件的元数据。谢谢
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);