使用PHP删除Amazon S3中的文件夹

12

我刚开始尝试使用Amazon S3来托管我的网站图片。我正在使用官方的Amazon AWS PHP SDK库。

问题:如何删除S3“文件夹”中的所有文件?
例如,如果我有一个名为images/2012/photo.jpg的文件,我想删除所有以images/2012/开头的文件。

5个回答

34

删除S3上包含所有文件的文件夹最好使用API deleteMatchingObjects()

$s3 = S3Client::factory(...);
$s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/some/dir');

请考虑@FranciscoCarmona的评论,我在此提供证据:

请注意一件事。如果您在“some”目录中有一个名为dirXXX.jpg的文件,那么它也将被删除。所以那不正确。您需要添加一个正则表达式。 $s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/some/dir', '/^some/dir//');


非常感谢你,Luigi。你让我的工作变得如此简单.. :) - Neeraj Rathod
如果没有引发异常,那么就意味着成功。检查deleteMatchingObjects()的返回值也很有用,它是一个整数,等于已删除键的数量。 - Luigi C.
4
请注意,如果您在“某个”目录中有一个名为dirXXX.jpg的文件,那么它将同时被删除。因此,这是不正确的。您需要添加一个正则表达式。 $s3->deleteMatchingObjects('YOUR_BUCKET_NAME', '/some/dir', '/^some/dir//'); - Francisco Carmona
很好的观察。我的解决方案基于通常情况下不会在同一级别混合文件和文件夹,而文件通常存储在每个层次结构的最终级别中。 - Luigi C.
1
请注意!正如@FranciscoCarmona所说,删除/some/dir将同时删除名为/some/dir123.jpg的文件。但它也会删除另一个名为/some/dir2的目录! - andreas
显示剩余2条评论

10

S3没有像传统文件系统上那样的“文件夹”(某些S3客户端使用巧妙的方式使S3看起来有文件夹)。这些/实际上是文件名的一部分。

因此,API中没有“删除文件夹”选项。您只需要删除具有images/2012/...前缀的每个单独的文件。

更新:

可以通过Amazon S3 PHP客户端中的delete_all_objects方法完成此操作。只需在第二个参数中指定"/^images\/2012\//"作为正则表达式前缀(第一个参数是您的存储桶名称)。


S3库中是否有任何函数可以选择所有文件名中包含特定字符串的文件? - Nyxynyx
是的,通过使用 delete_all_objects 方法可以删除所有对象。您可以指定一个正则表达式来删除与该表达式匹配的存储桶中的所有文件。有关详细信息和示例,请访问此处:http://docs.amazonwebservices.com/AWSSDKforPHP/latest/index.html#m=AmazonS3/delete_all_objects - nategood

0
$s3 = new Aws\S3\Client([ 'region' => 'us-west-2', 'version' => 'latest' ]); 
$listObjectsParams = ['Bucket' => 'foo', 'Prefix' => 'starts/with/']; 

// Asynchronously delete 
$delete = Aws\S3\BatchDelete::fromListObjects($s3, $listObjectsParams); 

// Force synchronous completion $delete->delete();
$promise = $delete->promise(); 

-1
这里有一个函数可以实现你想要的功能。
/**
*   This function will delete a directory.  It first needs to look up all objects with the specified directory
*   and then delete the objects.
*/
function Amazon_s3_delete_dir($dir){
    $s3 = new AmazonS3();

    //the $dir is the path to the directory including the directory

    // the directories need to have a / at the end.  
    // Clear it just in case it may or may not be there and then add it back in.
            $dir = rtrim($dir, "/");
            $dir = ltrim($dir, "/");
            $dir = $dir . "/";

    //get list of directories
        $response = $s3->get_object_list(YOUR_A3_BUCKET, array(
           'prefix' => $dir
        ));


    //delete each 
        foreach ($response as $v) {
            $s3->delete_object(YOUR_A3_BUCKET, $v);
        }//foreach

    return true;

}//function

使用: 如果我想要删除目录foo
Amazon_s3_delete_dir("path/to/directory/foo/");

3
你可以通过一次调用 delete_all_objects 来完成所有操作,而不是多次调用。这种方式也更加原子化。 - nategood
@nategood,不存在“更原子化”的概念。它要么是原子性的,要么不是。而这两种解决方案都不是原子性的。 - Dan Milon
是的。简洁一点会更好。这个操作不是原子性的。 - nategood
因为多次请求可能会超过请求限制,所以被踩了。有一个命令行可以代替foreach做到这一点。 - Marcelo Agimóvel

-1

我已经测试过了,它在2019年5月28日可以正常工作。

function Amazon_s3_delete_dir($delPath, $s3, $bucket) {
//the $dir is the path to the directory including the directory
// the directories need to have a / at the end.  
// Clear it just in case it may or may not be there and then add it back in.
$dir = rtrim($dir, "/");
$dir = ltrim($dir, "/");
$dir = $dir . "/";

$response = $s3->getIterator(
        'ListObjects',
        [
            'Bucket' => $bucket,
            'Prefix' => $delPath
        ]
);
//delete each 
foreach ($response as $object) {
    $fileName = $object['Key'];
    $s3->deleteObject([
        'Bucket' => $bucket,
        'Key' => $fileName
    ]);
}//foreach

    return true;
 }//function

使用方法:

$delPath = $myDir . $theFolderName . "/";        
Amazon_s3_delete_dir($delPath, $s3, $bucket);

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