2

Я получаю файл через:загрузить Force на ГКС через App Engine с использованием Подписана URL

require_once 'google/appengine/api/cloud_storage/CloudStorageTools.php';  
use google\appengine\api\cloud_storage\CloudStorageTools; 

$public_link = CloudStorageTools::getPublicUrl("gs://bucket/file.pdf", false); 

Если я иду в $public_link в браузере, она показывает PDF в браузере. Я пытаюсь выяснить, как я могу заставить загрузить этот файл.

Google App Engine имеет только 60-секундный тайм-аут, поэтому я боюсь, что служит Функция не работает через GAE. У кого-нибудь есть предложения?

-

EDIT

предыдущий ответ Андрея Volga на этом посту предлагает мне использовать Signed URL с response-content-distribution заголовком.

До сих пор я могу создать подписанный URL-адрес, который успешно показывает файл, но я не могу сгенерировать подписанный URL-адрес, который имеет какой-либо заголовок вообще. Создайте подписанный URL-адрес, который заставит загрузить вместо того, чтобы просто показывать его.

Это то, что у меня есть до сих пор, большинство из которых составляет courtesy of mloureiro.

function googleBuildConfigurationString($method, $expiration, $file, array $options = []) 
{ 
    $allowedMethods = ['GET', 'HEAD', 'PUT', 'DELETE']; 
    // initialize 
    $method = strtoupper($method); 
    $contentType = $options['Content_Type']; 
    $contentMd5 = $options['Content_MD5'] ? base64_encode($options['Content_MD5']) : ''; 
    $headers = $options['Canonicalized_Extension_Headers'] ? $options['Canonicalized_Extension_Headers'] . PHP_EOL : ''; 
    $file = $file ? $file : $options['Canonicalized_Resource']; 

    // validate 
    if(array_search($method, $allowedMethods) === false) 
    { 
     throw new RuntimeException("Method '{$method}' is not allowed"); 
    } 

    if(!$expiration) 
    { 
     throw new RuntimeException("An expiration date should be provided."); 
    } 

    return <<<TXT 
{$method} 
{$contentMd5} 
{$contentType} 
{$expiration} 
{$headers}{$file} 
TXT; 
    } 

function googleSignString($p12FilePath, $string) 
{ 
    $certs = []; 

    if (!openssl_pkcs12_read(file_get_contents($p12FilePath), $certs, 'notasecret')) 
    { 
     echo "Unable to parse the p12 file. OpenSSL error: " . openssl_error_string(); exit(); 
    } 

    $RSAPrivateKey = openssl_pkey_get_private($certs["pkey"]); 
    $signed = ''; 

    if(!openssl_sign($string, $signed, $RSAPrivateKey, 'sha256')) 
    { 
     error_log('openssl_sign failed!'); 
     $signed = 'failed'; 
    } 
    else $signed = base64_encode($signed); 

    return $signed; 
} 

function googleBuildSignedUrl($serviceEmail, $file, $expiration, $signature) 
{ 
    return "http://storage.googleapis.com{$file}" . "?GoogleAccessId={$serviceEmail}" . "&Expires={$expiration}" . "&Signature=" . urlencode($signature); 
} 

$serviceEmail = '<EMAIL>'; 
$p12FilePath = '../../path/to/cert.p12'; 
$expiration = (new DateTime())->modify('+3hours')->getTimestamp(); 
$bucket = 'bucket'; 
$fileToGet = 'picture.jpg'; 

$file = "/{$bucket}/{$fileToGet}"; 
$string = googleBuildConfigurationString('GET', $expiration, $file, array("Canonicalized_Extension_Headers" => '')); 
$signedString = googleSignString($p12FilePath, $string); 
$signedUrl = googleBuildSignedUrl($serviceEmail, $file, $expiration, $signedString); 

echo $signedUrl; 

ответ

1

Для небольших файлов, которые вы можете использовать serve вариант вместо публичного URL с save-as параметра установлено значение верно. См. documentation.

Для больших файлов вы можете использовать Signed URL с параметром response-content-disposition.

+0

Но если я обслуживаю файл размером 1 ГБ, не превысит ли это ограничение на 60 секунд? – bryan

+0

Он не будет работать ни для одного файла более 32 МБ - это предел для любого ответа на App Engine. Я уточню свой ответ. –

+0

Я могу получить подписанный URL-адрес успешно (проверьте предыдущее редактирование), но я не могу понять, как правильно получить заголовки. Какие-либо предложения? – bryan