[英]Force-Download with php on Amazon S3
我正在嘗試使用http://code.google.com/p/amazon-s3-php-class/從AWS S3強制下載文件。 我有一個MP3,希望人們“播放”或“下載”。 默認情況下,當您直接在s3上訪問文件時,它開始在瀏覽器中播放。 我需要添加一個選項才能實際下載。 我用Google搜索,發現什么都沒有。 我從概念上知道需要發生什么,但不知道如何生成php。 我知道我需要將標頭修改為Content-Disposition:附件。 任何幫助將不勝感激。
謝謝邁克爾
亞馬遜現在已經解決了這個問題,並允許在每個請求的基礎上使用已簽名的請求覆蓋標頭:
http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTObjectGET.html
w00t!
到目前為止已經提到的php腳本可以正常工作,但是主要的缺點是,每次您網站上的訪問者請求文件時,您自己的服務器都會從S3加載該文件,然后將該數據中繼到瀏覽器。 對於低流量站點,這可能沒什么大問題,但是對於高流量站點,您絕對要避免通過自己的服務器運行所有內容。
幸運的是,有一種相當簡單的方法可以將文件設置為強制從S3下載。 而且您說得很對-您只想設置content-type和content-disposition(僅設置content-disposition將在某些瀏覽器中起作用,但是同時設置這兩種設置在所有瀏覽器中都可以起作用)。
這段代碼假設您正在使用Undesigned的Amazon S3 PHP類:
<?php
// set S3 auth and get your bucket listing
// then loop through the bucket and copy each file over itself, replacing the "request headers":
S3::copyObject($bucketName, $filename, $bucketName, $filename, "public-read", array(), array("Content-Type" => "application/octet-stream", "Content-Disposition" => "attachment"));
?>
現在,您的所有文件將被強制下載。 您可能需要清除緩存以查看更改。 顯然,不要在您實際上希望在瀏覽器中“內聯”加載的任何文件上執行此操作。
此解決方案的優點在於,直接加載媒體文件的應用程序(例如Flash中的mp3播放器)無需關心內容類型或內容處置,因此您仍然可以在瀏覽器中播放文件,然后鏈接以下載相同的文件。 如果用戶已經完成了閃存文件的加載,他們很可能仍將其保存在緩存中,這意味着他們的下載將非常快捷,甚至不會從S3上花費您任何額外的帶寬費用。
只是想發表對此的貢獻,Alex Neth在此參考上是正確的,但是我不覺得使用亞馬遜自己的AWS PHP SDK2的鏈接是足夠的信息。 下面,我概述了一種以這種方式調用數據的基本(未調試)方法,您可以使用S3 Factory方法或AWS Service Builder來構建S3 Client。
<?php
// S3 Factory Method
/*use Aws\S3\S3Client;
$s3= S3Client::factory(array(
'key' => '<aws access key>',
'secret' => '<aws secret key>'
));*/
// OR AWS Service Builder
use Aws\Common\Aws;
// Create a service builder using a configuration file
$aws = Aws::factory('/path/to/my_config.json');
// Get the client from the builder by namespace
$s3 = $aws->get('S3');
// Now lets create our request object.
$command = $s3->getCommand('GetObject',array(
'Bucket' => 'your-bucket-name',
'Key' => 'keyname',
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="filename.mp3',
));
$url = $command->createPresignedUrl('+1 days');
?>
然后,您可以使用PHP的標頭(“ Location:$ url”); 為了通過強制下載將訪問者重定向到MP3文件,這應防止它在瀏覽器中播放,請注意,我非常頻繁地使用ResponseContentType,但我從未在AWS上使用過ResponseContentDisposition(它應根據文檔工作)。
將此示例轉換為函數應該很容易,您甚至可以像這樣傳遞$ bucket,$ key,$ force_download
<?php
use Aws\Common\Aws;
function gen_url($bucket,$key,$force_download=false){
// OR AWS Service Builder (personal method to do this)
// Create a service builder using a configuration file
$aws = Aws::factory('/path/to/my_config.json');
// Get the client from the builder by namespace
$s3 = $aws->get('S3');
$params = array(
'Bucket' => $bucket,
'Key' => 'keyname',
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="filename.mp3',
);
if($force_download){
$params['ResponseContentType'] = 'application/octet-stream';
$params['ResponseContentDisposition'] = 'attachment; filename="'.basename($key).'"';
}
$command = $s3->getCommand('GetObject',$params);
return $command->createPresignedUrl('+1 days');
}
// Location redirection to an MP3 force downlaod
header("Location: ".gen_url("recordings","my-file.mp3",true));
// Location redirection to a MP3 that lets the browser decide what to do.
header("Location: ".gen_url("recordings","my-file.mp3"));
?>
警告,如果您還沒有弄清楚,這需要當前(2014年4月7日)在這里找到AWS PHP SDK 2 http://aws.amazon.com/sdkforphp/此代碼主要是偽代碼,可能需要進行一些其他調整實際使工作,因為我從內存中引用了這一點。
只需在s3上將其添加到文件的元數據中即可:
Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
<?php
require_once __DIR__.'/vendor/autoload.php';
use Aws\Common\Aws;
function gen_url($bucket,$key,$force_download=false){
// OR AWS Service Builder (personal method to do this)
$config = array(
'key' => '',
'secret' => '',
);
// Create a service builder using a configuration file
$aws = Aws::factory($config);
// Get the client from the builder by namespace
$s3 = $aws->get('S3');
$params = array(
'Bucket' => $bucket,
'Key' => $key,
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="'.$key,
);
if($force_download){
$params['ResponseContentType'] = 'application/octet-stream';
$params['ResponseContentDisposition'] = 'attachment; filename="'.basename($key).'"';
}
$command = $s3->getCommand('GetObject',$params);
return $command->createPresignedUrl('+1 days');
}
$bucket = '';
$filename = '';
$url = gen_url($bucket,$filename,true);
echo "\n".$url."\n\n";
上面的代碼有效,您只需要安裝S3 composer依賴項並在自動加載文件中鏈接,將您的密鑰/秘密放入配置,然后提供存儲桶/文件名即可。
還值得一提的是,您可以在S3中硬設置文件頭。 例如,如果您需要強制下載某個文件,則可以為該文件設置適當的標題。 例如默認為流式傳輸,或者將輔助文件設置為強制下載或花費帶寬使用php / fputs並通過PHP強制下載。
所以修改我上面的例子是這樣的
<?php
header('Content-Type: audio/mpeg');
header("Content-Disposition: attachment; filename={$_GET['file']};");
readfile("url to the file/{$_GET['file']}");
exit();
?>
現在,您將要在其中進行一些驗證,以使您不會讓世界訪問您放在S3上的每個文件,但這應該可行。
如果您使用的是Tarzan AWS之類的庫,則可以添加元標頭,該標頭將在檢索文件時包含在Amazon中。 在此處簽出update_object函數中的meta參數,例如: http ://tarzan-aws.com/docs/2.0/files/s3-class-php.html#AmazonS3.update_object
現在可以通過使用簽名的請求覆蓋S3標頭來實現。
請求參數
有時您想覆蓋GET響應中的某些響應頭值。 例如,您可以在GET請求中覆蓋Content-Disposition響應標頭值。
您可以使用下表中列出的查詢參數覆蓋一組響應標題的值。
response-content- type-設置響應的Content-Type標頭response-content-disposition-設置響應的Content-Disposition標頭。
注意
使用這些參數時,必須使用授權標頭或預簽名的URL對請求進行簽名。 它們不能與未簽名(匿名)請求一起使用。
因此,您可以將這些標頭設置為:
response-content-disposition: attachment; filename=FILENAME.EXT
response-content-type: application/octet-stream
在這里找到答案: https : //stackoverflow.com/a/5903710/922522
php只會將文件下載到服務器,而不是客戶端。 記住,php在客戶端上不做任何事情,它只返回內容(html,javascript,css,xml等)。
[編輯:為清楚起見添加]:php可以提供音頻內容,但是您想同時提供網頁和音頻。 要獲得該客戶端的行為,您必須使客戶端根據網頁的html或javascript請求文件。
因此,您必須讓客戶端下載文件。 例如,在頁面上放置一個iframe,並在s3上添加文件的網址。 使用CSS使iframe不可見。 它應該呈現頁面並下載並播放mp3。
否則,請在頁面加載時考慮使用javascript進行下載。 我不確定是否可行。
<?php
// PHP solution (for OP and others), works with public and private files
// Download url expires after 30 minutes (no experation after the download initiates, for large files)
// ***Forces client download***
$signed_url = $s3_client->getObjectUrl($s3_bucket_name, $s3_filename_key, '+30 minutes', array(
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="your-file-name-here.mp4"'
));
redirect($signed_url);
我從未嘗試過Amazon的S3托管,但是您不可以在那里使用.htaccess文件嗎? 然后,您可以使用以下條目為整個目錄設置Content-Type和Content-Disposition:
<IfModule mod_headers.c>
<FilesMatch "\.(mp3)$">
ForceType audio/mpeg
Header set Content-Disposition attachment
</FilesMatch>
</IfModule>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.