【问题标题】:Is it possible to change headers on an S3 object without downloading the entire object?是否可以在不下载整个对象的情况下更改 S3 对象上的标头?
【发布时间】:2010-09-21 03:43:12
【问题描述】:

我已将一堆图像上传到 Amazon S3,现在想向它们添加一个 Cache-Control 标头。

可以在不下载整个图像的情况下更新标题吗?如果有,怎么做?

【问题讨论】:

  • x-amz-metadata-directive 标头不起作用。每次都会导致签名不匹配。所有其他 x-amz 标头都可以正常工作。

标签: amazon-s3


【解决方案1】:

这是测试版功能,但您可以在copy an object 时指定新的元数据。为副本指定相同的源和目标,这样只会更新对象上的元数据。

PUT /myObject HTTP/1.1
Host: mybucket.s3.amazonaws.com  
x-amz-copy-source: /mybucket/myObject  
x-amz-metadata-directive: REPLACE  
x-amz-meta-myKey: newValue

【讨论】:

  • 不要忘记在 headers 参数中包含对象的 Content-type,因为 PUT 请求会重写所有原始标头。
  • 一般来说,当源和目标相同时,复制操作会使用您提供的元数据重写所有元数据。有关x-amz-metadata-directive,请参阅documentation,它需要具有相同目标的复制请求以指定REPLACE。如果要保留现有用户或 S3 元数据,则需要获取现有对象的元数据、添加/更改条目并在复制请求中提供更新的元数据。
【解决方案2】:

这不是测试版,可以通过执行 put 命令并将对象复制为documented here 来使用。它也可以在他们的 SDK 中使用。以 C# 为例:

var s3Client = new AmazonS3Client("publicKey", "privateKey");
var copyRequest = new CopyObjectRequest()
                  .WithDirective(S3MetadataDirective.REPLACE)
                  .WithSourceBucket("bucketName")
                  .WithSourceKey("fileName")
                  .WithDestinationBucket("bucketName")
                  .WithDestinationKey("fileName)
                  .WithMetaData(new NameValueCollection { { "x-amz-meta-yourKey", "your-value }, { "x-amz-your-otherKey", "your-value" } });
var copyResponse = s3Client.CopyObject(copyRequest);

【讨论】:

  • @Scott hi,得到“尝试使用一个不可用或不再可用的对象。”使用新 API
【解决方案3】:

这就是您使用适用于 PHP 2 的 AWS 开发工具包的方式:

<?php
require 'vendor/autoload.php';

use Aws\Common\Aws;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;

const MONTH = 2592000;

// Instantiate an S3 client
$s3 = Aws::factory('config.php')->get('s3');
// Settings
$bucketName = 'example.com';
$objectKey = 'image.jpg';
$maxAge = MONTH;
$contentType = 'image/jpeg';

try {
    $o = $s3->copyObject(array(
        'Bucket' => $bucketName,
        'Key' => $objectKey,
        'CopySource' => $bucketName . '/'. $objectKey,
        'MetadataDirective' => 'REPLACE',
        'ACL' => CannedAcl::PUBLIC_READ,
        'command.headers' => array(
            'Cache-Control' => 'public,max-age=' . $maxAge,
            'Content-Type' => $contentType
        )
    ));

    // print_r($o->ETag);
} catch (Exception $e) {
    echo $objectKey . ': ' . $e->getMessage() . PHP_EOL;
}
?>

【讨论】:

    【解决方案4】:

    使用 amazon aws-sdk,使用额外标头执行 copy_object 似乎可以为现有 S3 对象设置缓存控制标头。

    ======================x======================== =======================

    <?php
        error_reporting(-1);
        require_once 'sdk.class.php';
    
        // UPLOAD FILES TO S3
            // Instantiate the AmazonS3 class
        $options = array("key" => "aws-key" , "secret" => "aws-secret") ;
    
    
            $s3 = new AmazonS3($options);
            $bucket = "bucket.3mik.com" ;
    
    
        $exists = $s3->if_bucket_exists($bucket);
        if(!$exists) {
            trigger_error("S3 bucket does not exists \n" , E_USER_ERROR);
        }
    
        $name = "cows-and-aliens.jpg" ;
        echo " change headers for $name  \n" ;
        $source = array("bucket" => $bucket, "filename" => $name);
        $dest = array("bucket" => $bucket, "filename" => $name);
    
        //caching headers
        $offset = 3600*24*365;
        $expiresOn = gmdate('D, d M Y H:i:s \G\M\T', time() + $offset);
        $headers = array('Expires' => $expiresOn, 'Cache-Control' => 'public, max-age=31536000');
    
           $meta = array('acl' => AmazonS3::ACL_PUBLIC, 'headers' => $headers);
    
        $response = $s3->copy_object($source,$dest,$meta);
        if($response->isOk()){
            printf("copy object done \n" );
    
        }else {
            printf("Error in copy object \n" );
        }
    
    ?>
    

    ========================x======================= ==========================

    【讨论】:

      【解决方案5】:

      在 Java 中,试试这个

      S3Object s3Object = amazonS3Client.getObject(bucketName, fileKey);
      ObjectMetadata metadata = s3Object.getObjectMetadata();
      Map customMetaData = new HashMap();
      customMetaData.put("yourKey", "updateValue");
      customMetaData.put("otherKey", "newValue");
      metadata.setUserMetadata(customMetaData);
      
      amazonS3Client.putObject(new PutObjectRequest(bucketName, fileId, s3Object.getObjectContent(), metadata));
      

      您也可以尝试复制对象。这里元数据不会在复制对象时复制。 您必须获取原始元数据并设置为复制请求。 更推荐使用此方法插入或更新 Amazon S3 对象的元数据

      ObjectMetadata metadata = amazonS3Client.getObjectMetadata(bucketName, fileKey);
      ObjectMetadata metadataCopy = new ObjectMetadata();
      metadataCopy.addUserMetadata("yourKey", "updateValue");
      metadataCopy.addUserMetadata("otherKey", "newValue");
      metadataCopy.addUserMetadata("existingKey", metadata.getUserMetaDataOf("existingValue"));
      
      CopyObjectRequest request = new CopyObjectRequest(bucketName, fileKey, bucketName, fileKey)
            .withSourceBucketName(bucketName)
            .withSourceKey(fileKey)
            .withNewObjectMetadata(metadataCopy);
      
      amazonS3Client.copyObject(request);
      

      【讨论】:

        【解决方案6】:

        这是 Python 中的帮助代码。

        import boto
        
        one_year  = 3600*24*365
        cckey = 'cache-control'
        s3_connection = S3Connection()
        bucket_name = 'my_bucket'
        bucket = s3_connection.get_bucket(bucket_name validate=False)
        
        
        for key in bucket:
            key_name = key.key
            if  key.size == 0: # continue on directories
                continue
            # Get key object
            key = bucket.get_key(key_name)
        
            if key.cache_control is not None:
                print("Exists")
                continue
        
            cache_time = one_year
            #set metdata
            key.set_metadata(name=cckey, value = ('max-age=%d, public' % (cache_time)))
            key.set_metadata(name='content-type', value = key.content_type)
            # Copy the same key
            key2 = key.copy(key.bucket.name, key.name, key.metadata, preserve_acl=True)
            continue
        
            

        说明:代码将新元数据添加到现有密钥,然后复制相同的文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-13
          • 2021-03-23
          • 1970-01-01
          相关资源
          最近更新 更多