如何用PHP删除AWS S3中早于指定时间的文件(Unauthenticated Ident池场景)
Got it, let's break this down and fix your problem step by step.
First off, I noticed you're using the older listobjects API—switching to listObjectsV2 (the recommended, more efficient version) will absolutely give you the LastModified timestamp for each object, which is exactly what you need to filter old files. The older listObjects does return this too, but maybe you missed it in the response structure? Either way, V2 is better for pagination and performance, so let's focus on that.
Solution 1: Use AWS SDK for PHP v3 to Find and Delete Old Objects
Here's a complete code example that handles listing objects, filtering by age, and bulk deleting them:
<?php require 'vendor/autoload.php'; use Aws\S3\S3Client; use Aws\Exception\AwsException; // Initialize S3 client $s3Client = new S3Client([ 'region' => 'your-region', 'version' => '2006-03-01', 'credentials' => [ // Use IAM credentials with s3:ListBucket and s3:DeleteObjects permissions 'key' => 'your-access-key', 'secret' => 'your-secret-key', ] ]); $bucketName = 'your-public-bucket'; $maxAgeDays = 7; // Delete files older than 7 days $cutoffTimestamp = strtotime("-$maxAgeDays days"); $oldObjects = []; $continuationToken = null; do { try { // List objects with pagination support $params = [ 'Bucket' => $bucketName, ]; if ($continuationToken) { $params['ContinuationToken'] = $continuationToken; } $result = $s3Client->listObjectsV2($params); // Iterate through each object and check LastModified foreach ($result['Contents'] as $object) { $lastModified = $object['LastModified']->getTimestamp(); if ($lastModified < $cutoffTimestamp) { $oldObjects[] = [ 'Key' => $object['Key'] ]; // Batch delete in chunks of 1000 (S3's limit for DeleteObjects) if (count($oldObjects) === 1000) { $s3Client->deleteObjects([ 'Bucket' => $bucketName, 'Delete' => [ 'Objects' => $oldObjects ] ]); $oldObjects = []; echo "Deleted 1000 old objects\n"; } } } $continuationToken = $result['NextContinuationToken'] ?? null; } catch (AwsException $e) { error_log($e->getMessage()); break; } } while ($continuationToken); // Delete any remaining objects if (!empty($oldObjects)) { $s3Client->deleteObjects([ 'Bucket' => $bucketName, 'Delete' => [ 'Objects' => $oldObjects ] ]); echo "Deleted " . count($oldObjects) . " remaining old objects\n"; } echo "Cleanup complete!\n"; ?>
Key notes about this code:
- It handles pagination, so even if your bucket has thousands of objects, it will keep fetching until all are checked.
- It batches deletes in chunks of 1000 (the maximum allowed by S3's
DeleteObjectsAPI) to avoid hitting rate limits. - Make sure your IAM credentials have the necessary permissions:
s3:ListBucket(to list objects) ands3:DeleteObjects(to delete them).
Solution 2: Use S3 Lifecycle Rules (Better, No Code Needed)
Honestly, the best approach for this scenario is to use S3's built-in lifecycle rules instead of writing custom code. Since you can't trust uploaders to set expiration dates, a bucket-level lifecycle rule will automatically delete old objects regardless of who uploaded them.
Here's how to set it up:
- Go to your S3 bucket in the AWS Console.
- Navigate to the Management tab.
- Click Create lifecycle rule.
- Name the rule (e.g., "DeleteOldAnonymousUploads").
- Under Rule scope, apply it to all objects in the bucket.
- Under Actions, add an Expire action, then set "Days after object creation" to your desired age (e.g., 7 days).
- Save the rule.
This is way more reliable than custom code—it runs automatically, handles all edge cases (like new uploads while your script is running), and doesn't require you to maintain a cron job or server to run the cleanup script.
Why You Didn't See the Timestamp Earlier
The original listobjects API does return the LastModified field, but it's a DateTime object in the PHP SDK response, not a raw timestamp. You might have overlooked it if you were just dumping the response without accessing the field properly.
内容的提问来源于stack exchange,提问作者Barkermn01

