2012-09-24 13 views
5

Używam poniższej funkcji php, aby dać tymczasowy dostęp do publicznie dla prywatnego pliku.Nie można zastąpić nagłówka zawartości w s3

function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds) { 
    $expires = time()+$expire_seconds; 
    // S3 Signed URL creation 
    $string_to_sign = "GET\n\n\n{$expires}\n/".str_replace(".s3.amazonAWS.com","", $bucket)."/$resource"; 
    $signature = urlencode(base64_encode((hash_hmac("sha1", utf8_encode($string_to_sign), $AWS_s3_secret_key, TRUE)))); 

    $authentication_params = "AWSAccessKeyId=".$AWS_S3_KEY; 
    $authentication_params.= "&Expires={$expires}"; 
    $authentication_params.= "&Signature={$signature}"; 

    return $link = "http://s3.amazonAWS.com/{$bucket}/{$resource}?{$authentication_params}"; 
}  

Chciałem dodać zawartość Disposition więc mogę zmienić nazwę pliku do test.mp3, gdy użytkownik próbuje uzyskać dostęp do tego URL, który domyślnie nazwa pliku do 982jdjd2p3.mp3

$privateUrl = array('privateUrl' => get_s3_signed_url('testbucket', '982jdjd2p3.mp3', $my_aws_key, $my_aws_secret_key, 60)); 

Próbowałem dodając następującą linię kodu do funkcji

$file_name = 'test.mp3';  
$authentication_params.= "&Content-Disposition={$file_name}"; 

jednak po kliknięciu na URL

http://s3.amazonAWS.com/testbucket/982jdjd2p3.mp3?AWSAccessKeyId=***&Expires=***&Signature=***&Content-Disposition=test.mp3

Proponowana nazwa pliku ma być zapisana jako 982jdjd2p3.mp3

Jak mogę nadpisać zawartości Disposition dla żądań GET s3 korzystania z tej funkcji?

Zobacz także

Amazon S3 Change file download name

EDIT

Oto najnowsza próba zmiany nazwy pliku z żądania GET przy użyciu tej funkcji.

function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds) { 
    $expires = time()+$expire_seconds; 
    // S3 Signed URL creation 
    $filename='moot.mp3'; 
    $disposition = "response-content-disposition=" . urlencode("attachment; filename={$filename}");    

    $string_to_sign = "GET\n\n\n{$expires}\n/".str_replace(".s3.amazonAWS.com","", $bucket)."/$resource"; 
    $string_to_sign .= "?{$disposition}"; 
    $signature = urlencode(base64_encode((hash_hmac("sha1", utf8_encode($string_to_sign), $AWS_s3_secret_key, TRUE)))); 

    $authentication_params = "AWSAccessKeyId=".$AWS_S3_KEY; 
    $authentication_params.= "&Expires={$expires}"; 
    $authentication_params.= "&Signature={$signature}"; 
    $authentication_params.= "&{$disposition}"; 

    return $link = "http://s3.amazonAWS.com/{$bucket}/{$resource}?{$authentication_params}"; 
}  

Odpowiedz

10

Problem z funkcji jest to, że wartości nagłówka powinny być zakodowane w końcowej hiperłącze, ale nie do podpisania. Następująca funkcja koryguje:

function get_s3_signed_url($bucket, $resource, $AWS_S3_KEY, $AWS_s3_secret_key, $expire_seconds, $save_as) 
{ 
    $expires = time()+$expire_seconds; 
    // S3 Signed URL creation 
    $headers = array(
     'response-content-disposition' => 'attachment; filename=' . $save_as, 
    ); 
    $resource = str_replace(array('%2F', '%2B'), array('/', '+'), rawurlencode($resource)); 

    $string_to_sign = "GET\n\n\n$expires\n/$bucket/$resource"; 
    $final_url = "http://s3.amazonaws.com/$bucket/$resource?"; 

    $append_char = '?'; 
    foreach ($headers as $header => $value) { 
     $final_url .= $header . '=' . urlencode($value) . '&'; 
     $string_to_sign .= $append_char . $header . '=' . $value; 
     $append_char = '&'; 
    } 

    $signature = urlencode(base64_encode(hash_hmac('sha1', $string_to_sign, $AWS_s3_secret_key, true))); 

    return $final_url . "AWSAccessKeyId=$AWS_S3_KEY&Expires=$expires&Signature=$signature"; 
} 
+0

Dzięki Jack! Jednak zapisuje się tylko jako tytuł do pierwszego miejsca. Na przykład, jeśli '$ save_as = 'hello world';' plik zostanie zapisany jako 'hello'. Jakikolwiek sposób obejścia tego? – user784637

+0

@ user784637 w takim przypadku warto rozważyć dodanie podwójnych cudzysłowów, np. 'filename =" hello world.txt "' –

1

Format swojej Content-Disposition jest nieprawidłowy, należy określić disposition-type.

Przykład: Content-Disposition: attachment; filename=test.mp3;

Zastosowanie response-content-disposition w podpisie i params:

$disposition = "response-content-disposition=" . urlencode("attachment; filename={$filename}"); 
/* ... */ 
$string_to_sign .= "?{$disposition}"; 
/* ... */ 
$authentication_params.= "&{$disposition}"; 
+0

Nie mam pojęcia, gdzie wprowadzić tę zmianę, czy mogę to zrobić w powyższym skrypcie php? Jaki jest odpowiedni kod? – user784637

+0

Edytowałem swoją odpowiedź. –

+0

Niestety, gdy próbuję, otrzymuję link do strony .xml z następującym błędem ** Obliczona przez nas sygnatura żądania nie pasuje do podanego przez ciebie podpisu. Sprawdź klucz i metodę podpisywania. ** – user784637

Powiązane problemy