使用PHP检查S3中对象是否存在

50

我正在使用PHP,并使用S3 API上传文件,但我想确保在上传之前存储桶中不存在完全相同的文件名。

我在网上找到了一些示例,使用了“file_get_contents”,但这不意味着您必须先下载整个文件吗?通常,这些文件大约有10 MB左右,所以最好不要这样做。

也许有一种方法可以使用“file_get_contents”而不必下载文件吗?

或者更好的是,也许我可以使用API请求来查看文件名是否存在?

对我来说,内容或文件大小是否相同并不重要,只要文件名相同即可。

5个回答

78

判断指定的Amazon S3存储桶中是否存在指定的对象。

AmazonS3 doesObjectExist

$s3 = new AmazonS3();
$bucket = 'my-bucket' . strtolower($s3->key);

$response = $s3->doesObjectExist($bucket, 'test1.txt');

// Success? (Boolean, not a CFResponse object)
var_dump($response);

3
此链接和方法适用于 AWS SDK for PHP 版本 1。更新的用户指南在此处:http://docs.aws.amazon.com/aws-sdk-php/latest/index.html,用于检查文件是否存在的相关部分使用流包装器,在此处找到:http://docs.aws.amazon.com/aws-sdk-php/guide/latest/feature-s3-stream-wrapper.html。 - David
3
更新后的文档链接,对应的确切方法是:http://docs.aws.amazon.com/aws-sdk-php/v2/api/class-Aws.S3.S3Client.html#_doesObjectExist - Andrei Diaconescu
2
应该使用正确的函数 $s3->doesObjectExist(...) - Brian Leishman
@BrianLeishman 感谢您指出。我已经更新了答案。 - waqas
1
v3文档链接:http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.S3ClientInterface.html#_doesObjectExist - Greg
显示剩余2条评论

12

尝试使用以下代码:

$s3 = new S3();

$info = $s3->getObjectInfo($bucket, $filename);
if ($info)
{
    echo 'File exists';
}
else
{
    echo 'File does not exists';
}

从亚马逊下载PHP的S3 SDK。有一个名为S3的类;创建一个S3对象。该对象将允许调用getObjectInfo()方法。传递您的S3存储桶名称和文件名(通常将文件名称为键)。如果文件存在,则getObjectInfo()方法将返回一些信息,否则该方法将返回FALSE。


1
一点解释会大大提高这个答案的质量。它目前在“低质量”审核队列中,可能是因为它主要由代码组成。 - Blorgbeard
谢谢您的评论。我刚刚解释了代码。 - Amir Md Amiruzzaman
这应该是最佳答案。最简单且最好的。 - George Chalhoub
嗨,我有一个问题,上面的方法好还是PHP的@getimagesize($filename))好?上面的代码只会作为GET请求,对吧? 但是PHP的getimagesize既会消耗带宽,又会进行GET请求,对吧? - WhiteHorse
我将文件名作为第二个参数添加,但它显示消息:S3 :: getObjectInfo(portal-static-assets,x1.xls):[403]意外的HTTP状态。 - FerdousTheWebCoder
请将文件名作为字符串“x1.xls”传递,看看是否有帮助。 - Amir Md Amiruzzaman

8
请注意,其他建议都基于AWS SDK for PHP的版本1。对于版本2,您需要熟悉最新指南,该指南在此处找到:http://docs.aws.amazon.com/aws-sdk-php/guide/latest/index.html
上面链接中的“入门”部分将帮助您安装和设置SDK,请仔细阅读这些文档,如果您还没有这样做,请花费时间阅读。完成设置后,您需要熟悉此处找到的流包装器方法:http://docs.aws.amazon.com/aws-sdk-php/guide/latest/feature-s3-stream-wrapper.html
最后,以下是一个简短的现实示例,说明如何在代码流程中使用它。
require('vendor/autoload.php');

// your filename
$filename = 'my_file_01.jpg';
// this will use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from env vars
$s3 = Aws\S3\S3Client::factory();
// S3_BUCKET must also be defined in env vars
$bucket = getenv('S3_BUCKET')?: die('No "S3_BUCKET" config var in found in env!');
// register stream wrapper method
$s3->registerStreamWrapper();
// does file exist
$keyExists = file_exists("s3://".$bucket."/".$filename);
if ($keyExists) {
    echo 'File exists!';
}

使用v2和$s3->registerStreamWrapper(),file_exists("s3://".$bucket."/".$filename)会返回一个"PHP致命错误:未捕获的Aws\S3\Exception\NoSuchKeyException异常:AWS错误代码:NoSuchKey,状态码:404",而不是true或false。看起来我需要捕获这个异常:( - Nick Weavers

3

如果您已经安装了PECL扩展HTTP或具备安装该扩展的能力,则可以使用http_head轻松进行头请求,并检查响应是否为200或404。


3

针对寻找v3及以上版本的任何人,这里提供更新版...

$s3Client = new \Aws\S3\S3Client([
    'version' => 'latest',
    'region' => getenv('AWS_REGION'),
    'credentials' => [
        'key' => getenv('AWS_KEY'),
        'secret' => getenv('AWS_SECRET')
    ]
]);
$response = $s3Client->doesObjectExist(getenv('AWS_S3_BUCKET'),'somefolder/somefile.ext');
if ($response) {
    echo "Yay, it exists :)";
} else {
    echo "Boo, nothing there :(";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接