Как обновить метаданные для существующего файла Amazon S3?

Мне нужно обновить заголовок управления кэшем во всех облачных файлах AmazonS3. Однако я не могу понять, как это сделать, используя API jclouds. Я использую плагин apache jclouds. И у меня есть два ответных ответа:

Первый ответ предполагает использовать класс SwiftKey Api, который недоступен в плагине grails jcloud. Второй ответ - использование AWS java sdk, для которого уже существует плагин wraps grails https://grails.org/plugin/aws-sdk, но он не поддерживает обновление метаданных.

Ответ 1

Можно изменить метаданные, выполнив копию объекта (см. Как обновить метаданные с помощью 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);

Независимо от того, философски ли это "обновление", вам решать.

Ответ 2

Вы не можете:

Каждый объект Amazon S3 имеет данные, ключ и метаданные. Ключ объекта (или имя ключа) однозначно идентифицирует объект в ведре. Метаданные объекта представляет собой набор пар имя-значение. Вы можете установить метаданные объекта в это время вы его загрузите. После загрузки объекта вы не можете изменять объект метаданные. Единственный способ изменить метаданные объекта - сделать копию объект и установить метаданные.

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

Ответ 3

Пример PHP

Я понимаю, что этот вопрос не был специфичным для PHP, но он может кому-то помочь, так как это лучший результат в Google.

Это перезапишет существующий объект.

$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

Ответ 4

По состоянию на март 2018 года изменилась последняя версия AWS SDK для .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);