AWS S3 - настройка метаданных с помощью PHP SDK2
Я пытаюсь изменить метаданные всех объектов в определенном сегменте на S3, используя AWS PHP SDK2. У меня были проблемы с поиском конкретного примера с использованием нового SDK, но я собрал следующее:
$OBJ_aws_s3 = S3Client::factory($config);
$objects = $OBJ_aws_s3->getIterator('ListObjects', array(
'Bucket' => $bucket,
'MaxKeys' => 10
));
foreach($objects as $object) {
$key = $object['Key'];
echo "Processing " . $key . "\n";
$response = $OBJ_aws_s3->copyObject(array(
'Bucket' => $bucket,
'Key' => $key,
'CopySource' => $key,
'Metadata' => array(
'Cache-Control' => 'max-age=94608000',
'Expires' => gmdate('D, d M Y H:i:s T', strtotime('+3 years'))
),
'MetadataDirective' => 'REPLACE',
));
}
foreach
цикл успешно перебирает первые 10 элементов в данном $bucket, но я получаю ошибку 403 на copyObject()
операция:
Uncaught Aws\S3\Exception\AccessDeniedException: AWS Error Code: AccessDenied, Status Code: 403
Я не уверен, связано ли это с неправильными значениями, передаваемыми в copyObject, или с некоторыми настройками в S3. Обратите внимание, что мне еще предстоит создать учетную запись с ограниченными правами в IAM, и я использую базовую учетную запись, которая должна иметь все права на объекты.
Любая помощь приветствуется.
2 ответа
Хорошо, понял это - мой синтаксис был неверным в двух отношениях.
Во-первых, я использовал неправильное значение для CopySource
, Из документации:
CopySource - (строка) - имя исходного сегмента и имя ключа исходного объекта, разделенные косой чертой (/). Должен быть в кодировке URL.
Так что в моем случае вместо использования просто 'CopySource' => $key,
, так должно быть 'CopySource' => urlencode($bucket . '/' . $key),
, Это объясняет ошибки 403, поскольку я, по сути, говорил API, что мой исходный файл был в {bucket} / {key} просто {key}.
Вторая проблема связана с конкретными заголовками - указанием заголовков Expires и Cache-Control в Metadata
поле приводит к созданию специфичных для Amazon мета-значений с ключами с префиксом x-amz-meta-
, Вместо этого я сейчас использую Expires
а также CacheControl
аргументы. Мой последний рабочий код:
$OBJ_aws_s3 = S3Client::factory($config);
$objects = $OBJ_aws_s3->getIterator('ListObjects', array(
'Bucket' => $bucket,
'MaxKeys' => 10
));
foreach($objects as $object) {
$key = $object['Key'];
echo "Processing " . $key . "\n";
$response = $OBJ_aws_s3->copyObject(array(
'Bucket' => $bucket,
'Key' => $key,
'CopySource' => urlencode($bucket . '/' . $key),
'CacheControl' => 'max-age=94608000',
'Expires' => gmdate('D, d M Y H:i:s T', strtotime('+3 years')),
'MetadataDirective' => 'COPY',
));
}
Расширил исходный ответ Пола Меннеги, чтобы сохранить ContentTypes по умолчанию при обновлении файлов в существующей корзине с использованием 'MetadataDirective' => 'REPLACE'
вместо КОПИИ.
`
//
// Utility to add cache-control and expires headers to existing files in an S3 Bucket
// Defaults to 1 Year which is the RFC spec max.
//
// Requirements:
// AWS PHP SDK
// http://aws.amazon.com/sdkforphp/
// Set your TIMEZONE
// http://www.php.net//manual/en/timezones.php
date_default_timezone_set("Australia/Adelaide");
// CONFIG START
$bucket = "YOUR-BUCKET-NAME-HERE";
$aws_key = "YOUR-AWS-KEY";
$aws_secret = "YOUR-AWS-SECRET";
// CONFIG END
require 'vendor/autoload.php';
use Aws\S3\S3Client;
$filetype = "";
$count = 0;
$OBJ_aws_s3 = S3Client::factory(array(
'key' => $aws_key,
'secret' => $aws_secret
));
$objects = $OBJ_aws_s3->getIterator('ListObjects', array(
'Bucket' => $bucket,
'MaxKeys' => 10
));
foreach($objects as $object) {
$key = $object['Key'];
echo "Processing " . $key . "\n";
$file_parts = pathinfo($key);
switch($file_parts['extension'])
{
case "jpg":
echo "ContentType set to: image/jpeg" . "\n\n";
$filetype = "image/jpeg";
break;
case "jpeg":
echo "ContentType set to: image/jpeg" . "\n\n";
$filetype = "image/jpeg";
break;
case "png":
echo "ContentType set to: image/png" . "\n\n";
$filetype = "image/png";
break;
case "gif":
echo "ContentType set to: image/gif" . "\n\n";
$filetype = "image/gif";
break;
case "tif":
echo "ContentType set to: image/tiff" . "\n\n";
$filetype = "image/tiff";
break;
case "tiff":
echo "ContentType set to: image/tiff" . "\n\n";
$filetype = "image/tiff";
break;
case "bmp":
echo "ContentType set to: image/bmp" . "\n\n";
$filetype = "image/bmp";
break;
case "zip":
echo "ContentType set to: application/zip" . "\n\n";
$filetype = "application/zip";
break;
case "pdf":
echo "ContentType set to: application/pdf" . "\n\n";
$filetype = "application/pdf";
break;
case "": // Handle file extension for files ending in '.'
echo "Error: Unknown ContentType" . "\n\n";
$filetype = "";
break;
case NULL: // Handle no file extension
echo "Error: Unknown ContentType" . "\n\n";
$filetype = "";
break;
}
// Set EXPIRES and CACHE-CONTROL headers to +1 year (RFC guidelines max.)
$response = $OBJ_aws_s3->copyObject(array(
'Bucket' => $bucket,
'Key' => $key,
'CopySource' => urlencode($bucket . '/' . $key),
'MetadataDirective' => 'REPLACE',
'CacheControl' => 'max-age=31536000',
'Expires' => gmdate('D, d M Y H:i:s T', strtotime('+1 years')),
'ContentType' => $filetype,
));
$count++;
}
echo "DONE! processed ". $count ." files.\n";
`