duan0821 2019-05-07 09:47
浏览 108
已采纳

数字海洋:如何将所需的ContentMD5添加到生命周期,cors或acl的Bucket Policy PUT请求?

I am going to answer my own question here. It took me hours to figure this out as there is no info on this anywhere so I thought I should post this somewhere I would look first.

I was using the AWS PHP SDK to send a PUT request to add a lifecycle policy to my Digital Ocean space and it would not take since it requires a ContentMD5 header. There are two problems here, the first problem is the SDK URL encodes the path/key, which is a problem with /?lifecycle, /?location, and /?acl since they become "/%3Flifecycle" -- skip this paragraph if this isn't part of your request path. To temporarily stop this to add or update a bucket policy you have to find the file RestSerializer.php in the SDK files, if you added the API with composer it will be in a path like /vendor/aws/aws-sdk-php/src/Api/Serializer/RestSerializer.php in your composer/websites root, which will likely be in /var/www. In RestSerializer.php find the two rawurlencode function calls and remove them but leave the value/argument "rawurlencode($varspecs[$k])" becomes "$varspecs[$k]".

Now the request is going to the correct URL, to generate the ContentMD5 you need to construct a little PHP code depending on what you're doing. If you have put the XML text for your policy in a file use md5_file(PATH_TO_FILE_HERE, true) if you are using a string use md5(STRING_HERE, true). Then wrap that in base64_encode() so it looks something like base64_encode(md5_file('/path/file.xml', true)). Finally, add that to your putObject array with 'ContentMD5' => base64_encode(md5_file('/path/file.xml', true)) .

PHP Example with File:

// $spaceS3Client is a new S3Client object.

// since its a file, I need to get the file first
$xmlfile = fopen('/spaces.xml', 'r+');

$request = $spaceS3Client->putObject([
  'Bucket' => 'myspacename',
  'Key' => '?lifecycle',
  'Body' => $xmlfile,
  'ContentType' => 'application/xml',
  'ContentMD5' => base64_encode(md5_file('/spaces.xml'', true))
]);

// close file
fclose($xmlfile);

// if you are having trouble connecting to your space in the first place with an S3Client object, since its set up for AWS and not DO you need to add an 'endpoint' to the array in new S3Client like 'endpoint' => 'https://'.$myspace.'.'.$myspaceregion.'.digitaloceanspaces.com'. You also need to add 'bucket_endpoint' => true.
  • 写回答

1条回答 默认 最新

  • doupinyan0186 2019-05-07 13:04
    关注

    There are two problems here, the first problem is the SDK URL encodes the path/key, which is a problem with /?lifecycle, /?location, and /?acl since they become "/%3Flifecycle" -- skip this paragraph if this isn't part of your request path. To temporarily stop this to add or update a bucket policy you have to find the file RestSerializer.php in the SDK files, if you added the API with composer it will be in a path like /vendor/aws/aws-sdk-php/src/Api/Serializer/RestSerializer.php in your composer/websites root, which will likely be in /var/www. In RestSerializer.php find the two rawurlencode function calls and remove them but leave the value/argument "rawurlencode($varspecs[$k])" becomes "$varspecs[$k]".

    Now the request is going to the correct URL, to generate the ContentMD5 you need to construct a little PHP code depending on what you're doing. If you have put the XML text for your policy in a file use md5_file(PATH_TO_FILE_HERE, true) if you are using a string use md5(STRING_HERE, true). Then wrap that in base64_encode() so it looks something like base64_encode(md5_file('/path/file.xml', true)). Finally, add that to your putObject array with 'ContentMD5' => base64_encode(md5_file('/path/file.xml', true)) .

    PHP Example with File:

    // $spaceS3Client is a new S3Client object.
    
    // since its a file, I need to get the file first
    $xmlfile = file_get_contents('/spaces.xml', 'r+');
    
    $request = $spaceS3Client->putObject([
      'Bucket' => 'myspacename',
      'Key' => '?lifecycle',
      'Body' => $xmlfile,
      'ContentType' => 'application/xml',
      'ContentMD5' => base64_encode(md5_file('/spaces.xml', true))
    ]);
    
    // if you are having trouble connecting to your space in the first place with an S3Client object, since its set up for AWS and not DO you need to add an 'endpoint' to the array in new S3Client like 'endpoint' => 'https://'.$myspace.'.'.$myspaceregion.'.digitaloceanspaces.com'. You also need to add 'bucket_endpoint' => true.
    
    // to check the rules have been set use a getObject request and then use the code below to parse the response.
    
    header('Content-type: text/xml');
    $request = $request->toArray()["Body"];
    echo $request;
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥17 pro*C预编译“闪回查询”报错SCN不能识别
  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向