如何设置S3文件夹中所有文件的ACL

How to set ACL of all files in a folder in S3

我想使用 Java 授予对 S3 中文件夹内所有文件的读取权限。我正在使用 TransferManager 进行文件夹上传,但我没有找到任何 API 来在目录级别

上设置 ACL

MultipleFileUpload upload = transferManager.uploadDirectory(bucketName, uploadDirectory, new File(folderName), true);

我知道我可以使用以下方法设置 S3 对象的 ACL: s3.setObjectAcl(bucketName, key, acl);

但我想同时对一个文件夹中的所有文件执行此操作。有什么办法吗?

S3中没有文件夹,只有bucket和key。为方便起见,共享一个公共前缀的键在控制台中组合在一起,但在引擎盖下,结构是完全扁平的。因此,无法为文件夹设置 ACL。但是有一些解决方法。

使用存储桶策略

根据您要授予的权限和授予的权限,您可以使用存储桶策略授予对 "folder" 中所有密钥的访问权限。此示例允许任何人从存储桶 my-bucket 中获取文件夹 path/to/folder/ 下的任何密钥。这是来自文档的 list of possible actions and a list of possible principals

{
    "Version":"2012-10-17",
    "Statement":[
        {
            "Sid":"SimulateFolderACL",
            "Effect":"Allow",
            "Principal": "*",
            "Action":["s3:GetObject"],
            "Resource":["arn:aws:s3:::my-bucket/path/to/folder/*"]
        }
    ]
}

迭代并将 ACL 应用于每个键

您还可以遍历所有键并直接应用 ACL,就像您提到的使用 s3.setObjectAcl(bucketName, key, acl) 一样。您可以按文件夹前缀过滤密钥,这样您就不必直接检查每个密钥名称。目录上传后,你可以这样做:

// We only want the keys that are in the folder
ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
                                            .withBucketName("my-bucket")
                                            .withPrefix("path/to/folder/");
ObjectListing objectListing;

// Iterate over all the matching keys     
do {
    objectListing = s3client.listObjects(listObjectsRequest);
    for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries())
    {
            // Apply the ACL
            s3.setObjectAcl(bucketName, key, acl);
    }
    listObjectsRequest.setMarker(objectListing.getNextMarker());
} while (objectListing.isTruncated());

以下简单方法为存储桶中的所有对象提供 public-读取。

void makeObjectsPublic(AmazonS3 s3Client, String bucketName) {

    final Iterator<S3ObjectSummary> itr = s3Client.listObjects(bucketName).getObjectSummaries().iterator();

    while (itr.hasNext()) {
        s3Client.setObjectAcl(bucketName, itr.next().getKey(), CannedAccessControlList.PublicRead);
    }
}