Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用签名URL通过应用程序引擎在地面军事系统上强制下载_Php_Google App Engine_Google Cloud Storage_Pre Signed Url - Fatal编程技术网

Php 使用签名URL通过应用程序引擎在地面军事系统上强制下载

Php 使用签名URL通过应用程序引擎在地面军事系统上强制下载,php,google-app-engine,google-cloud-storage,pre-signed-url,Php,Google App Engine,Google Cloud Storage,Pre Signed 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\u

我通过以下方式获取我的文件:

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\u link
,它会在浏览器中显示PDF。我正在试图找出如何强制下载此文件

谷歌应用程序引擎只有60秒的超时时间,因此我担心通过GAE无法使用服务功能。有人有什么建议吗

--

编辑

安德烈·伏尔加(Andrei Volga)此前在这篇文章中的回答建议我使用带有
响应内容分发
标题的签名URL

到目前为止,我能够创建一个成功显示文件的签名URL,但我无法生成一个具有任何类型头的签名URL,即创建一个将强制下载的签名URL,而不仅仅是显示它

这就是我到目前为止所拥有的,其中大部分是

函数googleBuildConfigurationString($method、$expiration、$file、array$options=[]))
{
$allowedMethods=['GET','HEAD','PUT','DELETE'];
//初始化
$method=strtoupper($method);
$contentType=$options['Content_-Type'];
$contentMd5=$options['Content\u MD5']?base64\u编码($options['Content\u MD5']):'';
$headers=$options['Canonicalized_Extension_headers']?$options['Canonicalized_Extension_headers']。PHP_EOL:“”;
$file=$file?$file:$options['Canonicalized_Resource'];
//证实
if(数组搜索($method,$allowedMethods)==false)
{
抛出新的RuntimeException(“不允许使用方法“{$Method}”);
}
如果(!$expiration)
{
抛出新的RuntimeException(“应提供到期日期”);
}
返回getTimestamp();
$bucket='bucket';
$fileToGet='picture.jpg';
$file=“/{$bucket}/{$fileToGet}”;
$string=googleBuildConfigurationString('GET',$expiration,$file,array(“规范化的_扩展名_头”=>“”));
$signedString=googleSignString($p12FilePath,$string);
$signedUrl=googleBuildSignedUrl($serviceEmail,$file,$expiration,$signedString);
echo$signedUrl;

对于小文件,您可以使用
服务
选项,而不是将
另存为
选项设置为true的公共URL。请参阅


对于大文件,您可以使用with
response content disposition
参数。

但如果我提供的是1GB文件,这不会超过60秒的限制吗?对于任何超过32MB的文件,这都不起作用-这是App Engine上任何响应的限制。我将更新我的答案。我能够成功获得签名URL(检查以前的编辑)但我不知道如何获得正确的标题。有什么建议吗?这是我Java代码中的一个片段。您可以修改它:
.append(“&response content disposition=“).append(urlcoder.encode(“attachment;filename=“+”\”+”+“\”+”file.name+“\”,“UTF-8”))
因此,基本上,您需要添加
&response content disposition=attachment;filename=
,后跟一个文件名。我会对其进行URL编码,但如果您事先知道文件名并且文件名是URL安全的(例如,没有空格等),则不需要这样做
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;