我正在尝试将我的网站图像从我的主机移动到Amazon S3云托管。这些图像属于客户工作站点,无法公开。我希望它们能够在我的网站上显示,最好是使用亚马逊提供的PHP SDK。
到目前为止,我已经能够为转换编写脚本,以便在数据库中查找记录,获取文件路径,对其进行适当命名,然后将其发送到亚马逊。
//upload to s3
$s3->create_object($bucket, $folder.$file_name_new, array(
'fileUpload' => $file_temp,
'acl' => AmazonS3::ACL_PRIVATE, //access denied, grantee only own
//'acl' => AmazonS3::ACL_PUBLIC, //image displayed
//'acl' => AmazonS3::ACL_OPEN, //image displayed, grantee everyone has open permission
//'acl' => AmazonS3::ACL_AUTH_READ, //image not displayed, grantee auth users has open permissions
//'acl' => AmazonS3::ACL_OWNER_READ, //image not displayed, grantee only ryan
//'acl' => AmazonS3::ACL_OWNER_FULL_CONTROL, //image not displayed, grantee only ryan
'storage' => AmazonS3::STORAGE_REDUCED
)
);
在我复制所有内容之前,我创建了一个简单的表单来测试上传和显示图像。如果我使用ACL_PRIVATE上传图像,我可以获取公共网址,但我无权访问,或者我可以使用临时密钥获取公共网址并显示图像。
<?php
//display the image link
$temp_link = $s3->get_object_url($bucket, $folder.$file_name_new, '1 minute');
?>
<a href='<?php echo $temp_link; ?>'><?php echo $temp_link; ?></a><br />
<img src='<?php echo $temp_link; ?>' alt='finding image' /><br />
使用此方法,我的缓存将如何工作?我猜每次刷新页面或修改我的一条记录时,我都会再次拉动该图像,增加我的获取请求。
我还考虑过使用存储桶策略只允许从某些引用来检索图像。我是否正确理解亚马逊应该仅从我指定的页面或域中获取请求?
我引用了: https://forums.aws.amazon.com/thread.jspa?messageID=188183𭼗设置它,但后来我对我的对象需要哪种安全性感到困惑。看起来如果我将它们设为私有它们仍然不会显示,除非我使用前面提到的临时链接。如果我将它们公之于众,我可以直接导航到它们,无论引用者是谁。
我离开了我想要做的事吗?这不是S3真的支持,还是我错过了一些简单的东西?我已经完成了SDK文档和大量搜索,并且觉得这应该更清楚地记录下来,所以希望这里的任何输入都能在这种情况下帮助其他人。我读过其他人用文件命名这个文件的唯一ID,通过默默无闻来创造安全性,但这不会在我的情况下削减它,对于任何想要保证安全的人来说,这可能不是最好的做法。
答案 0 :(得分:24)
提供图片的最佳方式是使用PHP SDK生成网址。这样下载就会直接从S3发送到您的用户。
您无需通过@mfonda建议的服务器下载 - 您可以在S3对象上设置您喜欢的任何缓存标头 - 如果您这样做,您将失去使用S3的一些主要好处。
但是,正如您在问题中指出的那样,url将始终在更改(实际上是查询字符串),因此浏览器不会缓存该文件。简单的解决方法就是始终使用相同的到期日期,以便始终生成相同的查询字符串。或者更好的是自己“缓存”网址(例如在数据库中)并且每次都重复使用它。
您显然必须在未来的某个地方设置到期时间,但如果您愿意,可以经常重新生成这些网址。例如,在您的数据库中,您将存储生成的URL和到期日期(您也可以从URL解析)。然后,您只需使用现有的URL,或者如果过期日期已过,则生成一个新的URL。等...
答案 1 :(得分:8)
您可以在Amazon存储桶中使用存储桶策略,以允许应用程序的域访问该文件。实际上,您甚至可以将本地开发域(例如:mylocaldomain.local)添加到访问列表中,您将能够获取图像。亚马逊在此处提供了示例存储桶策略:http://docs.aws.amazon.com/AmazonS3/latest/dev/AccessPolicyLanguage_UseCases_s3_a.html。这对帮助我提供图像非常有帮助。
下面的政策解决了让我参与这个SO主题的问题:
{
"Version":"2008-10-17",
"Id":"http referer policy example",
"Statement":[
{
"Sid":"Allow get requests originated from www.example.com and example.com",
"Effect":"Allow",
"Principal":"*",
"Action":"s3:GetObject",
"Resource":"arn:aws:s3:::examplebucket/*",
"Condition":{
"StringLike":{
"aws:Referer":[
"http://www.example.com/*",
"http://example.com/*"
]
}
}
}
]
}
答案 2 :(得分:2)
当您谈论安全性并保护数据免受未经授权的用户攻击时,有些事情是明确的:您必须在每次访问您有权访问的资源时进行检查。
这意味着,生成一个可以被任何人访问的URL(可能很难获得,但仍然......)。唯一的解决方案是图像代理。你可以用PHP脚本来做到这一点。
来自亚马逊博客的一篇精彩文章使用readfile http://blogs.aws.amazon.com/php/post/Tx2C4WJBMSMW68A/Streaming-Amazon-S3-Objects-From-a-Web-Server
进行提取readfile('s3://my-bucket/my-images/php.gif');
答案 3 :(得分:0)
您可以从S3下载内容(在PHP脚本中),然后使用正确的标题提供它们。
作为一个粗略的例子,假设您在image.php
中有以下内容:
$s3 = new AmazonS3();
$response = $s3->get_object($bucket, $image_name);
if (!$response->isOK()) {
throw new Exception('Error downloading file from S3');
}
header("Content-Type: image/jpeg");
header("Content-Length: " . strlen($response->body));
die($response->body);
然后在您的HTML代码中,您可以
<img src="image.php">