我正在尝试使用http://code.google.com/p/amazon-s3-php-class/从 AWS S3 强制下载文件。我有一个我希望人们“播放”或“下载”的 mp3。默认情况下,当您直接在 s3 上访问文件时,它开始在浏览器中播放。我需要添加一个选项来实际下载。我用谷歌搜索并发现什么都没有。我从概念上知道需要发生什么,但不知道如何生成它 php。我知道我需要将标题修改为 Content-Disposition: 附件。任何帮助将不胜感激。
谢谢,迈克尔
我正在尝试使用http://code.google.com/p/amazon-s3-php-class/从 AWS S3 强制下载文件。我有一个我希望人们“播放”或“下载”的 mp3。默认情况下,当您直接在 s3 上访问文件时,它开始在浏览器中播放。我需要添加一个选项来实际下载。我用谷歌搜索并发现什么都没有。我从概念上知道需要发生什么,但不知道如何生成它 php。我知道我需要将标题修改为 Content-Disposition: 附件。任何帮助将不胜感激。
谢谢,迈克尔
亚马逊现在已经解决了这个问题,并允许在每个请求的基础上使用签名请求覆盖标头:
http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTObjectGET.html
w00t!
到目前为止已经提到的 php 脚本可以正常工作,但主要的缺点是每次您网站上的访问者请求文件时,您自己的服务器将从 S3 加载它,然后将该数据中继到浏览器。对于低流量站点,这可能没什么大不了的,但对于高流量站点,您绝对希望避免通过您自己的服务器运行所有内容。
幸运的是,有一种相当直接的方法可以将您的文件设置为强制从 S3 下载。你说得对——你只想设置 content-type 和 content-disposition (只是设置 content-disposition 将在某些浏览器中工作,但设置两者都应该在所有浏览器中工作)。
此代码假设您使用 Undesign 中的 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 中花费任何额外的带宽费用。
只需将其添加到 s3 上的文件元数据中:
Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
只是想对此发表贡献,Alex Neth 在此参考上是正确的,但我认为使用亚马逊自己的 AWS PHP SDK2 的链接信息不足。下面我概述了一种以这种方式调用数据的基本(未经测试)方法,您可以使用 S3 工厂方法或 AWS Service Builder 来制作 S3 客户端。
<?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 的 header("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/此代码主要是伪代码,可能需要一些额外的调整当我从内存中引用它时,实际工作。
所以把我上面的例子修改成这样
<?php
header('Content-Type: audio/mpeg');
header("Content-Disposition: attachment; filename={$_GET['file']};");
readfile("url to the file/{$_GET['file']}");
exit();
?>
现在您需要在其中进行一些验证,这样您就不会让世界访问您放在 S3 上的每个文件,但这应该可以工作。
如果您使用的是Tarzan AWS之类的库,您可以添加元标头,亚马逊将在检索文件时包含该标头。在此处查看 update_object 函数中的元参数,例如: http ://tarzan-aws.com/docs/2.0/files/s3-class-php.html#AmazonS3.update_object
另外值得一提的是,您可以在 S3 中硬设置文件的标题。例如,如果您需要强制下载某个文件,您可以为该文件设置适当的标题。例如默认流式传输,或者将辅助文件设置为强制下载,或者花费带宽使用 php/fputs 并通过 PHP 强制下载。
<?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 依赖项和链接,将你的密钥/秘密放入配置,然后提供存储桶/文件名。
php 只会将文件下载到服务器,而不是客户端。请记住,php 在客户端上不做任何事情,它只是返回内容(html、javascript、css、xml 等等……)
[编辑:为清楚起见添加]:php 可以提供音频内容,但您希望同时提供网页和音频。要获得该客户端行为,您必须让客户端根据网页的 html 或 javascript 请求文件。
所以你必须让客户端下载文件。例如,在页面上有一个 iframe,文件的 url 在 s3 上。使用 css 使 iframe 不可见。它应该呈现页面并下载和播放 mp3。
否则,请考虑在页面加载时使用 javascript 来启动下载。我不确定这是否可能。
现在可以通过使用签名请求覆盖 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
<?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>