Zend Framework 1.12 Amazon S3 CopyObject SignatureDoesNotMatch

时间:2016-10-03 12:11:31

标签: php zend-framework amazon-s3

使用ZF 1.11我使用$ s3-> copyObject()没有问题。我需要升级到ZF 1.12.20,但是当尝试复制对象时我得到了这个错误:

Zend_Http_Response::__set_state(array(
'version' => '1.1',
'code' => 403,
'message' => 'Forbidden',
'headers' =>
array (
'X-amz-request-id' => '07295DAF1500709B',
'X-amz-id-2' => '6zkAaIx0FHCZvgetRaMfCp6h6SfbHVbJoCrHqNdKN6AcfywOrrBCcSD13RcKvfiDBOJjiEm+ldM=',
'Content-type' => 'application/xml',
'Transfer-encoding' => 'chunked',
'Date' => 'Fri, 30 Sep 2016 12:30:03 GMT',
'Server' => 'AmazonS3',
'Connection' => 'close',
),
'body' => '610
SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and     signing method.AKIAJK6QI4DTZQ2X2SFAPUT
application/x-www-form-urlencoded
Fri, 30 Sep 2016 12:30:03 +0000
x-amz-copy-source:imgdeverasmusu/259/not-quite-reaching-potential-5f601d2088d7afc4fe69e1800bedc1cf.jpg
x-amz-metadata-directive:COPY
/imgdeverasmusu/259/eq-db37b6972b19800eaf310011ae00ffc2.jpg

如果我将类Zend_Http_Client 1.12.20更改为1.11,则副本可以使用,但不能使用1.12.20。

1 个答案:

答案 0 :(得分:0)

<?php

//导致错误的更改是这样的:         if((($ method == self :: POST || $ method == self :: PUT || $ method == self :: DELETE)&& $ this-> enctype === null){             $ this-> setEncType(self :: ENC_URLENCODED);         }

//在ZF 1.11.1上是: //如果(($ method == self :: POST && $ this-> enctype === null){ // $ this-> setEncType(self :: ENC_URLENCODED); //}

//因此,解决方法是将编码设置为false(值!== null) //我创建了一个扩展Zend_Service_Amazon_S3的新类,在其中添加了以下行: $ client-> setEncType(false);

MyApp_Service_Amazon_S3类扩展了Zend_Service_Amazon_S3 {

public function _makeRequest($method, $path='', $params=null, $headers=array(), $data=null)
{
    $retry_count = 0;

    if (!is_array($headers)) {
        $headers = array($headers);
    }

    $headers['Date'] = gmdate(DATE_RFC1123, time());

    if (is_resource($data) && $method != 'PUT') {
        /**
         * @see Zend_Service_Amazon_S3_Exception
         */
        require_once 'Zend/Service/Amazon/S3/Exception.php';
        throw new Zend_Service_Amazon_S3_Exception("Only PUT request supports stream data");
    }

    // build the end point out
    $parts = explode('/', $path, 2);
    $endpoint = clone($this->_endpoint);
    if ($parts[0]) {
        // prepend bucket name to the hostname
        $endpoint->setHost($parts[0] . '.' . $endpoint->getHost());
    }
    if (!empty($parts[1])) {
        // ZF-10218, ZF-10122
        $pathparts = explode('?', $parts[1]);
        $endpath = $pathparts[0];
        $endpoint->setPath('/' . $endpath);
    } else {
        $endpoint->setPath('/');
        if ($parts[0]) {
            $path = $parts[0] . '/';
        }
    }
    self::addSignature($method, $path, $headers);

    $client = self::getHttpClient();

    $client->resetParameters(true);
    $client->setUri($endpoint);
    $client->setAuth(false);
    // Work around buglet in HTTP client - it doesn't clean headers
    // Remove when ZHC is fixed
    /*
      $client->setHeaders(array('Content-MD5'              => null,
      'Content-Encoding'         => null,
      'Expect'                   => null,
      'Range'                    => null,
      'x-amz-acl'                => null,
      'x-amz-copy-source'        => null,
      'x-amz-metadata-directive' => null));
     */
    $client->setHeaders($headers);

    // Workaround to fix enctype bug
    $client->setEncType(false);

    if (is_array($params)) {
        foreach ($params as $name => $value) {
            $client->setParameterGet($name, $value);
        }
    }

    if (($method == 'PUT') && ($data !== null)) {
        if (!isset($headers['Content-type'])) {
            $headers['Content-type'] = self::getMimeType($path);
        }
        $client->setRawData($data, $headers['Content-type']);
    }
    do {
        $retry = false;

        $response = $client->request($method);
        $response_code = $response->getStatus();

        // Some 5xx errors are expected, so retry automatically
        if ($response_code >= 500 && $response_code < 600 && $retry_count <= 5) {
            $retry = true;
            $retry_count++;
            sleep($retry_count / 4 * $retry_count);
        } else if ($response_code == 307) {
            // Need to redirect, new S3 endpoint given
            // This should never happen as Zend_Http_Client will redirect automatically
        } else if ($response_code == 100) {
            // echo 'OK to Continue';
        }
    } while ($retry);

    return $response;
}

}