0

以下のように、署名付きの Amazon S3 URL を生成する PHP 関数があります。

  if(!function_exists('el_crypto_hmacSHA1')){
    /**
    * Calculate the HMAC SHA1 hash of a string.
    *
    * @param string $key The key to hash against
    * @param string $data The data to hash
    * @param int $blocksize Optional blocksize
    * @return string HMAC SHA1
    */
    function el_crypto_hmacSHA1($key, $data, $blocksize = 64) {
        if (strlen($key) > $blocksize) $key = pack('H*', sha1($key));
        $key = str_pad($key, $blocksize, chr(0x00));
        $ipad = str_repeat(chr(0x36), $blocksize);
        $opad = str_repeat(chr(0x5c), $blocksize);
        $hmac = pack( 'H*', sha1(
        ($key ^ $opad) . pack( 'H*', sha1(
          ($key ^ $ipad) . $data
        ))
      ));
        return base64_encode($hmac);
    }
  }

  if(!function_exists('el_s3_getTemporaryLink')){
    /**
    * Create temporary URLs to your protected Amazon S3 files.
    *
    * @param string $accessKey Your Amazon S3 access key
    * @param string $secretKey Your Amazon S3 secret key
    * @param string $bucket The bucket (bucket.s3.amazonaws.com)
    * @param string $path The target file path
    * @param int $expires In minutes
    * @return string Temporary Amazon S3 URL
    * @see http://awsdocs.s3.amazonaws.com/S3/20060301/s3-dg-20060301.pdf
    */

    function el_s3_getTemporaryLink($accessKey, $secretKey, $bucket, $path, $expires = 5) {
      // Calculate expiry time
      $expires = time() + intval(floatval($expires) * 60);
      // Fix the path; encode and sanitize
      $path = str_replace('%2F', '/', rawurlencode($path = ltrim($path, '/')));
      // Path for signature starts with the bucket
      $signpath = '/'. $bucket .'/'. $path;
      // S3 friendly string to sign
      $signsz = implode("\n", $pieces = array('GET', null, null, $expires, $signpath));
      // Calculate the hash
      $signature = el_crypto_hmacSHA1($secretKey, $signsz);
      // Glue the URL ...
      $url = sprintf('https://%s/%s', $bucket, $path);
      // ... to the query string ...
      $qs = http_build_query($pieces = array(
        'AWSAccessKeyId' => $accessKey,
        'Expires' => $expires,
        'Signature' => $signature,
      ));
      // ... and return the URL!
      return $url.'?'.$qs;
    }

    }

zipファイルをダウンロードするために使用するフォームボタンのあるページが1つあります。

<?php
// Grab the file url
$file_url = get_post_meta($post->ID, 'file_url', true);
// Grab just the filename with extension
$file_name = basename($file_url); 

// AWS details                  
$accessKey = "AKIAJJLX2F7GUDTQ23AA";
$secretKey = "<REMOVED>";
$bucket_name = "media.themixtapesite.com";

// Create new S3 Expiry URL
$download_url = el_s3_getTemporaryLink($accessKey, $secretKey, $bucket_name, $file_name);


if (is_user_logged_in()) { ?>
<div class="download_button_div">
<?php echo '<form action="'.$download_url.'" class="download_button_div">'; ?>
<!--Download counter-->
<input type="hidden" name="download_counter" value="<?php (int)$download_count = get_post_meta($post->ID, 'download_counter', true);
$download_count++;
update_post_meta($post->ID, 'download_counter', $download_count); ?>">
<button type='submit' class='download_button'>Download</button>
</form>

ご覧のとおり、フォーム アクションをダウンロードしたいファイルの URL に設定するだけです。これはうまくいきます。署名済みの有効期限のある S3 URL を生成し、ファイルをダウンロードします。

別のページでは、同じ機能を使用していますが、フォームが少し異なります。これは、単一の mp3 ファイルをダウンロードすることです。

<?php
// Grab the file url
$file_url = $mp3s;
// Grab just the filename with extension
$file_name = basename($file_url); 

// AWS details                  
$accessKey = "AKIAJJLX2F7GUDTQ23AA";
$secretKey = "<REMOVED>";
$bucket_name = "mixtape2.s3.amazonaws.com";

// Create new S3 Expiry URL
$download_url = el_s3_getTemporaryLink($accessKey, $secretKey, $bucket_name, $file_name);
?>

<!--Download individual MP3 file direct from player-->

<span style="right:27px; position:absolute;">
<form action="download_file.php" method="post" name="downloadform">
<input name="file_name" value="<?php echo basename($mp3s); ?>" type="hidden">
<input name="real_file" value="<?php echo $download_url; ?>" type="hidden">
<input type="image" src="download.jpg" border="0" width="17" alt="Download the MP3" />
</form>

このフォームでわかるように、処理のために「download_file.php」という別のファイルに POST を使用してフォームを送信します。「download_file.php」は、ブラウザで開くのではなく、mp3 ファイルを強制的にダウンロードする単純なファイルです。

<?php
if(isset($_POST['file_name'])){
$player_file = $_POST['file_name'];
header('Content-type: audio/mpeg3');
header('Content-Disposition: attachment; filename="themixtapesite_'.$player_file.'"');
readfile($_POST['real_file']);
exit();
}
?>

私が抱えている問題は、2 番目のページ ('download_file.php に送信する場所) で、生成された URL が機能しないことです。フォームを送信すると、0kb のファイルがダウンロードされます。ソースを表示し、リンクをコピーしてブラウザーに貼り付けると、署名が一致しないことを示す S3 エラー メッセージが表示されます。

最初のページが機能するのに、2 番目のページが機能しない理由がわかりません。URL は両方とも同じ関数を使用して生成されますか??

どんな助けでも感謝します。

4

1 に答える 1

0

発見してくれた@oriqueのおかげで、バケット名を間違って入力しました。愚かな間違い...失明のコーディング!

于 2013-02-05T15:14:13.680 に答える