6

我正在尝试使用 AWS PHP SDK2 更改 S3 上特定存储桶中所有对象的元数据。我很难找到使用新 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循环成功地遍历了给定 $bucket 中的前 10 个项目,但我在操作中收到 403错误copyObject()

Uncaught Aws\S3\Exception\AccessDeniedException: AWS Error Code: AccessDenied, Status Code: 403

我不确定这是否是由于传递给 copyObject 的值不正确,还是因为 S3 中的某些设置。请注意,我尚未在 IAM 中创建权限受限帐户,并且正在使用应该对对象拥有所有权限的基本帐户。

任何帮助表示赞赏。

4

2 回答 2

10

好的,想通了 - 我的语法在两个方面不正确。

首先,我使用了不正确的值CopySource。从文档中:

CopySource - (string) - 源存储桶的名称和源对象的键名,以斜杠 (/) 分隔。必须是 URL 编码的。

所以在我的情况下,而不是使用 just 'CopySource' => $key,,它应该是'CopySource' => urlencode($bucket . '/' . $key),. 这解释了 403 错误,因为我实际上是在告诉 API 我的源文件位于 {bucket} / {key} 中,只有 {key}。

第二个问题与特定标头有关 - 在字段中指定 Expires 和 Cache-Control 标头会Metadata导致创建特定于 Amazon 的元值,其键前缀为x-amz-meta-. 相反,我现在使用ExpiresandCacheControl参数。我的最终工作代码:

$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',
    ));
}
于 2013-05-15T04:03:24.807 回答
0

'MetadataDirective' => 'REPLACE'扩展了 Paul Mennega 的原始答案,以在使用而不是 COPY更新现有存储桶中的文件时保留默认 ContentTypes 。

`

//
// 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";

`

于 2014-06-27T02:44:24.720 回答