如何将上传的图像存储到 PHP 上的 AWS S3
How could I store uploaded images to AWS S3 on PHP
我在 EC2 实例上,我希望将我的 PHP 网站连接到我的 Amazon S3 存储桶,我已经在此处看到 PHP 的 API:http://aws.amazon.com/sdkforphp/ 但不清楚。
这是我需要在控制器中编辑的代码行:
thisFu['original_img']='/uploads/fufu/'.$_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
我需要连接到 Amazon S3 并能够像这样更改代码:
$thisFu['original_img']='my_s3_bucket/uploads/fufu/'.$_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
我已经为此目的配置了一个 IAM 用户,但我不知道完成这项工作所需的所有步骤。
如何连接 Amazon S3 并与其交互以上传和检索 public 图像?
更新
我决定按照建议尝试使用 s3fs,所以我按照描述安装了它 here(我的 OS 是 Ubuntu 14.04)
我 运行 来自控制台:
sudo apt-get install build-essential git libfuse-dev libcurl4-openssl-dev libxml2-dev mime-support automake libtool
sudo apt-get install pkg-config libssl-dev
git clone https://github.com/s3fs-fuse/s3fs-fuse
cd s3fs-fuse/
./autogen.sh
./configure --prefix=/usr --with-openssl
make
sudo make install
一切都已正确安装,但下一步是什么?我应该在哪里声明凭据以及如何在我的项目中使用此集成?
第二次更新
我用我的 IAM 凭据 accessKeyId:secretAccessKey
创建了一个名为 .passwd-s3fs
的文件,其中只有一行代码。
我将它放入我的 home/ubuntu
目录中并使用 chmod 600 ~/.passwd-s3fs
授予它 600 权限
下一步从控制台 I 运行 /usr/bin/s3fs My_S3bucket /uploads/fufu
现在 /uploads/fufu
里面有我所有的存储桶文件夹。但是当我尝试这个命令时:
s3fs -o nonempty allow_other My_S3bucket /uploads/fufu
我收到此错误消息:
s3fs: unable to access MOUNTPOINT My_S3bucket : No such file or directory
第三次更新
按照我的建议 运行 这个 fusermount -u /uploads/fufu
,之后我检查了 fufu 文件夹并且如预期的那样是空的。
之后我再次尝试这个命令(还有一个 -o):
s3fs -o nonempty -o allow_other My_S3bucket /uploads/fufu
并收到此错误消息:
fusermount: failed to open /etc/fuse.conf: Permission denied
fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf
还有其他建议吗?
第四次更新 18/04/15
根据控制台的建议,我 运行 sudo usermod -a -G fuse ubuntu
和 sudo vim /etc/fuse.conf
我取消注释 mount_max = 1000 和 user_allow_other
比我运行 s3fs -o nonempty -o allow_other My_S3bucket /uploads/fufu
乍一看没有错误,所以我认为一切都很好,但事实恰恰相反。
我现在有点沮丧,因为我不知道发生了什么,但我的文件夹 /uploads/fufu
被隐藏并使用 ls -Al
我只看到这个
d????????? ? ? ? ? ? fufu
我不能 sudo rm -r
或 -rf
或 mv -r
它说 /uploads/fufu is a directory
我试过 reboot exit and mount -a
,但没有。
我尝试使用 fusermount
卸载,错误消息是 fusermount: entry for /uploads/fufu not found in /etc/mtab
但我尝试了 sudo vim /etc/mtab 并且我发现了这一行:s3fs /uploads/fufu fuse.s3fs rw,nosuid,nodev,allow_other 0 0
谁能告诉我如何卸载并最终删除此文件夹 /uploads/fufu
?
我同意 link 的文档有点难以挖掘并且留下了很多要连接的点。
不过,我在这里发现了更好的东西:http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html
它包含几乎所有 S3 操作的示例代码和说明。
为了让您更清楚一点,因为您是初学者:通过此 Installation Guide
下载 AWS SDK
然后使用此位
在 PHP 网络服务器上设置您的 AWS 帐户客户端
use Aws\S3\S3Client;
$client = S3Client::factory(array('profile' => '<profile in your aws credentials file>'
));
如果您想了解有关如何使用 AWS 凭证文件的更多信息,head here.
然后上传您自己 PHP 服务器上的文件:
$result = $client->putObject(array(
'Bucket' => $bucket,
'Key' => 'data_from_file.txt',
'SourceFile' => $pathToFile,
'Metadata' => array(
'Foo' => 'abc',
'Baz' => '123'
)
));
如果您有兴趣学习如何将图像上传到 php 文件,我建议您查看 this W3 schools tutorial. 本教程可以帮助您开始将文件保存到您的本地服务器在临时目录中,然后再上传到您的 S3 存储桶。
对您的应用程序设置来说更简单和透明的方法是使用 s3fs 安装 s3 分区
https://github.com/s3fs-fuse/s3fs-fuse
(使用选项 allow_other)
然后,您的 s3fs 的行为就像普通文件夹一样,只会将文件移动到该文件夹。 S3fs 然后上传
S3fs 在最近的构建中非常可靠
您也可以通过这种方式读取图像,但是会失去 AWS CDN 的任何效果,虽然我上次尝试过它并没有太大的区别
您需要一个 s3fspassword 文件
格式
accessKeyId:secretAccessKey
它可以在这些地方之一
using the passwd_file command line option
setting the AWSACCESSKEYID and AWSSECRETACCESSKEY environment variables
using a .passwd-s3fs file in your home directory
using the system-wide /etc/passwd-s3fs file
文件需要600权限
https://github.com/s3fs-fuse/s3fs-fuse/wiki/Fuse-Over-Amazon
有一些信息。
完成后,命令为 s3fs bucket_name mnt_dir
你可以在这里找到钥匙
https://console.aws.amazon.com/iam/home?#security_credential
根据关于我假设你的 mnt_dir
的例子是 /uploads/fufu
所以s3fs bucket /uploads/fufu
你的第二个问题
s3fs -o nonempty allow_other My_S3bucket /uploads/fufu
错误,需要重新指定-o
s3fs -o nonempty -o allow_other My_S3bucket /uploads/fufu
您要安装的用户需要在保险丝组中
sudo usermod -a -G fuse your_user
或
sudo addgroup your_user fuse
尽管 "S3fs is very reliable in recent builds",我可以分享我自己的 s3fs 经验和信息,我们将写操作从直接 s3fs 安装的文件夹访问移动到 aws 控制台(SDK api 也可能的方式)在定期之后系统随机崩溃。
您可能不会对图像等小文件有任何问题,但当我们尝试编写 mp4 文件时,它肯定会产生问题。所以系统崩溃前日志中的最后一条消息是:
kernel: [ 9180.212990] s3fs[29994]: segfault at 0 ip 000000000042b503 sp 00007f09b4abf530 error 4 in s3fs[400000+52000]
随机出现的情况很少见,但这会使系统不稳定。
所以我们决定仍然挂载 s3fs,但仅将其用于读取访问
下面我展示了如何在没有密码文件的情况下使用 AIM 凭据挂载 s3fs
#!/bin/bash -x
S3_MOUNT_DIR=/media/s3
CACHE_DIR=/var/cache/s3cache
wget http://s3fs.googlecode.com/files/s3fs-1.74.tar.gz
tar xvfz s3fs-1.74.tar.gz
cd s3fs-1.74
./configure
make
make install
mkdir $S3_MOUNT_DIR
mkdir $CACHE_DIR
chmod 0755 $S3_MOUNT_DIR
chmod 0755 $CACHE_DIR
export IAMROLE=`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/`
/usr/local/bin/s3fs $S3_BUCKET $S3_MOUNT_DIR -o iam_role=$IAMROLE,rw,allow_other,use_cache=$CACHE_DIR,uid=222,gid=500
您还需要创建分配给具有附加策略的实例的 IAM 角色:
{"Statement":[{"Resource":"*","Action":["s3:*"],"Sid":"S3","Effect":"Allow"}],"Version":"2012-10-17"}
在你的情况下,似乎使用 php sdk 是合理的(其他答案已经有使用示例),但你也可以使用 aws 控制台将图像写入 s3:
aws s3 cp /path_to_image/image.jpg s3://your_bucket/path
如果您将创建 IAM 角色并将其分配给您的实例,则无需提供任何额外的凭证
更新 - 回答你的问题:
- 我不需要包含工厂方法来声明我的 IAM 凭证吗?
是的,如果您将 IAM 分配给 ec2 实例,那么在代码中您只需将客户端创建为:
$s3Client = S3Client::factory();
$bucket = 'my_s3_bucket';
$keyname = $_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
$localFilePath = '/local_path/some_image.jpg';
$result = $s3Client->putObject(array(
'Bucket' => $bucket,
'Key' => $keyname,
'SourceFile' => $filePath,
'ACL' => 'public-read',
'ContentType' => 'image/jpeg'
));
unlink($localFilePath);
选项 2:如果您不需要文件本地存储阶段,但会直接从上传表单中放置:
$s3Client = S3Client::factory();
$bucket = 'my_s3_bucket';
$keyname = $_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
$dataFromFile = file_get_contents($_FILES['uploadedfile']['tmp_name']);
$result = $s3Client->putObject(array(
'Bucket' => $bucket,
'Key' => $keyname,
'Body' => $dataFromFile,
'ACL' => 'public-read',
));
并获取 s3 link 如果您将具有 public 访问权限
$publicUrl = $s3Client->getObjectUrl($bucket, $keyname);
或生成签名url到私人内容:
$validTime = '+10 minutes';
$signedUrl = $s3Client->getObjectUrl($bucket, $keyname, $validTime);
我在 EC2 实例上,我希望将我的 PHP 网站连接到我的 Amazon S3 存储桶,我已经在此处看到 PHP 的 API:http://aws.amazon.com/sdkforphp/ 但不清楚。
这是我需要在控制器中编辑的代码行:
thisFu['original_img']='/uploads/fufu/'.$_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
我需要连接到 Amazon S3 并能够像这样更改代码:
$thisFu['original_img']='my_s3_bucket/uploads/fufu/'.$_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
我已经为此目的配置了一个 IAM 用户,但我不知道完成这项工作所需的所有步骤。
如何连接 Amazon S3 并与其交互以上传和检索 public 图像?
更新
我决定按照建议尝试使用 s3fs,所以我按照描述安装了它 here(我的 OS 是 Ubuntu 14.04)
我 运行 来自控制台:
sudo apt-get install build-essential git libfuse-dev libcurl4-openssl-dev libxml2-dev mime-support automake libtool
sudo apt-get install pkg-config libssl-dev
git clone https://github.com/s3fs-fuse/s3fs-fuse
cd s3fs-fuse/
./autogen.sh
./configure --prefix=/usr --with-openssl
make
sudo make install
一切都已正确安装,但下一步是什么?我应该在哪里声明凭据以及如何在我的项目中使用此集成?
第二次更新
我用我的 IAM 凭据 accessKeyId:secretAccessKey
创建了一个名为 .passwd-s3fs
的文件,其中只有一行代码。
我将它放入我的 home/ubuntu
目录中并使用 chmod 600 ~/.passwd-s3fs
下一步从控制台 I 运行 /usr/bin/s3fs My_S3bucket /uploads/fufu
现在 /uploads/fufu
里面有我所有的存储桶文件夹。但是当我尝试这个命令时:
s3fs -o nonempty allow_other My_S3bucket /uploads/fufu
我收到此错误消息:
s3fs: unable to access MOUNTPOINT My_S3bucket : No such file or directory
第三次更新
按照我的建议 运行 这个 fusermount -u /uploads/fufu
,之后我检查了 fufu 文件夹并且如预期的那样是空的。
之后我再次尝试这个命令(还有一个 -o):
s3fs -o nonempty -o allow_other My_S3bucket /uploads/fufu
并收到此错误消息:
fusermount: failed to open /etc/fuse.conf: Permission denied
fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf
还有其他建议吗?
第四次更新 18/04/15
根据控制台的建议,我 运行 sudo usermod -a -G fuse ubuntu
和 sudo vim /etc/fuse.conf
我取消注释 mount_max = 1000 和 user_allow_other
比我运行 s3fs -o nonempty -o allow_other My_S3bucket /uploads/fufu
乍一看没有错误,所以我认为一切都很好,但事实恰恰相反。
我现在有点沮丧,因为我不知道发生了什么,但我的文件夹 /uploads/fufu
被隐藏并使用 ls -Al
我只看到这个
d????????? ? ? ? ? ? fufu
我不能 sudo rm -r
或 -rf
或 mv -r
它说 /uploads/fufu is a directory
我试过 reboot exit and mount -a
,但没有。
我尝试使用 fusermount
卸载,错误消息是 fusermount: entry for /uploads/fufu not found in /etc/mtab
但我尝试了 sudo vim /etc/mtab 并且我发现了这一行:s3fs /uploads/fufu fuse.s3fs rw,nosuid,nodev,allow_other 0 0
谁能告诉我如何卸载并最终删除此文件夹 /uploads/fufu
?
我同意 link 的文档有点难以挖掘并且留下了很多要连接的点。
不过,我在这里发现了更好的东西:http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html
它包含几乎所有 S3 操作的示例代码和说明。
为了让您更清楚一点,因为您是初学者:通过此 Installation Guide
下载 AWS SDK然后使用此位
在 PHP 网络服务器上设置您的 AWS 帐户客户端use Aws\S3\S3Client;
$client = S3Client::factory(array('profile' => '<profile in your aws credentials file>'
));
如果您想了解有关如何使用 AWS 凭证文件的更多信息,head here.
然后上传您自己 PHP 服务器上的文件:
$result = $client->putObject(array(
'Bucket' => $bucket,
'Key' => 'data_from_file.txt',
'SourceFile' => $pathToFile,
'Metadata' => array(
'Foo' => 'abc',
'Baz' => '123'
)
));
如果您有兴趣学习如何将图像上传到 php 文件,我建议您查看 this W3 schools tutorial. 本教程可以帮助您开始将文件保存到您的本地服务器在临时目录中,然后再上传到您的 S3 存储桶。
对您的应用程序设置来说更简单和透明的方法是使用 s3fs 安装 s3 分区
https://github.com/s3fs-fuse/s3fs-fuse
(使用选项 allow_other) 然后,您的 s3fs 的行为就像普通文件夹一样,只会将文件移动到该文件夹。 S3fs 然后上传
S3fs 在最近的构建中非常可靠
您也可以通过这种方式读取图像,但是会失去 AWS CDN 的任何效果,虽然我上次尝试过它并没有太大的区别
您需要一个 s3fspassword 文件
格式 accessKeyId:secretAccessKey
它可以在这些地方之一
using the passwd_file command line option
setting the AWSACCESSKEYID and AWSSECRETACCESSKEY environment variables
using a .passwd-s3fs file in your home directory
using the system-wide /etc/passwd-s3fs file
文件需要600权限
https://github.com/s3fs-fuse/s3fs-fuse/wiki/Fuse-Over-Amazon
有一些信息。
完成后,命令为 s3fs bucket_name mnt_dir
你可以在这里找到钥匙
https://console.aws.amazon.com/iam/home?#security_credential
根据关于我假设你的 mnt_dir
的例子是 /uploads/fufu
所以s3fs bucket /uploads/fufu
你的第二个问题
s3fs -o nonempty allow_other My_S3bucket /uploads/fufu
错误,需要重新指定-o
s3fs -o nonempty -o allow_other My_S3bucket /uploads/fufu
您要安装的用户需要在保险丝组中
sudo usermod -a -G fuse your_user
或 sudo addgroup your_user fuse
尽管 "S3fs is very reliable in recent builds",我可以分享我自己的 s3fs 经验和信息,我们将写操作从直接 s3fs 安装的文件夹访问移动到 aws 控制台(SDK api 也可能的方式)在定期之后系统随机崩溃。
您可能不会对图像等小文件有任何问题,但当我们尝试编写 mp4 文件时,它肯定会产生问题。所以系统崩溃前日志中的最后一条消息是:
kernel: [ 9180.212990] s3fs[29994]: segfault at 0 ip 000000000042b503 sp 00007f09b4abf530 error 4 in s3fs[400000+52000]
随机出现的情况很少见,但这会使系统不稳定。
所以我们决定仍然挂载 s3fs,但仅将其用于读取访问
下面我展示了如何在没有密码文件的情况下使用 AIM 凭据挂载 s3fs
#!/bin/bash -x
S3_MOUNT_DIR=/media/s3
CACHE_DIR=/var/cache/s3cache
wget http://s3fs.googlecode.com/files/s3fs-1.74.tar.gz
tar xvfz s3fs-1.74.tar.gz
cd s3fs-1.74
./configure
make
make install
mkdir $S3_MOUNT_DIR
mkdir $CACHE_DIR
chmod 0755 $S3_MOUNT_DIR
chmod 0755 $CACHE_DIR
export IAMROLE=`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/`
/usr/local/bin/s3fs $S3_BUCKET $S3_MOUNT_DIR -o iam_role=$IAMROLE,rw,allow_other,use_cache=$CACHE_DIR,uid=222,gid=500
您还需要创建分配给具有附加策略的实例的 IAM 角色:
{"Statement":[{"Resource":"*","Action":["s3:*"],"Sid":"S3","Effect":"Allow"}],"Version":"2012-10-17"}
在你的情况下,似乎使用 php sdk 是合理的(其他答案已经有使用示例),但你也可以使用 aws 控制台将图像写入 s3:
aws s3 cp /path_to_image/image.jpg s3://your_bucket/path
如果您将创建 IAM 角色并将其分配给您的实例,则无需提供任何额外的凭证
更新 - 回答你的问题:
- 我不需要包含工厂方法来声明我的 IAM 凭证吗?
是的,如果您将 IAM 分配给 ec2 实例,那么在代码中您只需将客户端创建为:
$s3Client = S3Client::factory();
$bucket = 'my_s3_bucket';
$keyname = $_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
$localFilePath = '/local_path/some_image.jpg';
$result = $s3Client->putObject(array(
'Bucket' => $bucket,
'Key' => $keyname,
'SourceFile' => $filePath,
'ACL' => 'public-read',
'ContentType' => 'image/jpeg'
));
unlink($localFilePath);
选项 2:如果您不需要文件本地存储阶段,但会直接从上传表单中放置:
$s3Client = S3Client::factory();
$bucket = 'my_s3_bucket';
$keyname = $_POST['cat'].'/original_'.uniqid('fu_').'.jpg';
$dataFromFile = file_get_contents($_FILES['uploadedfile']['tmp_name']);
$result = $s3Client->putObject(array(
'Bucket' => $bucket,
'Key' => $keyname,
'Body' => $dataFromFile,
'ACL' => 'public-read',
));
并获取 s3 link 如果您将具有 public 访问权限
$publicUrl = $s3Client->getObjectUrl($bucket, $keyname);
或生成签名url到私人内容:
$validTime = '+10 minutes';
$signedUrl = $s3Client->getObjectUrl($bucket, $keyname, $validTime);