Amazon Java S3 SDK - UploadDirectory

2019-07-08 09:39发布

问题:

I am using the Java Amazon S3 SDK to upload files I was wondering - when using the transferManager to upload a directory - is there a better way to set the Acl to be public-read

Here is my code

public boolean uploadDirectoryToAmazon(String directory, String bucketName, String s3DirectoryKey) {
    boolean result = false;

    try {
        LOGGER.info("Uploading a directory to S3");

        BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretAccessKey); 
        AWSStaticCredentialsProvider awsStaticCredentialsProvider = new AWSStaticCredentialsProvider(credentials);

        AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withCredentials(awsStaticCredentialsProvider)
                .withRegion(amazonS3Region)
                .build();

        //PutObjectResult putObjectResult = s3Client.putObject(putObjectRequest);
        //http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferManager.html
        TransferManager transferManager = TransferManagerBuilder.
                standard().
                withS3Client(s3Client)
                .build();


                    ObjectMetadataProvider objectTaggingProvider = new ObjectMetadataProvider() {
            public void provideObjectMetadata(File file, ObjectMetadata metadata) {
                if (BooleanUtils.isTrue(isPublic)) {
                    metadata.setHeader(Headers.S3_CANNED_ACL, CannedAccessControlList.PublicRead);
                }
            }
        };

        File dirToUpload = new File(directory);
        MultipleFileUpload uploadDirectoryResult = transferManager.uploadDirectory(bucketName, s3DirectoryKey, dirToUpload, false, objectMetadataProvider);

        //Call method to log the progress
        logProgress(uploadDirectoryResult);            

        result = true;  
        transferManager.shutdownNow();
     } catch (AmazonServiceException ase) {
        LOGGER.error("Caught an AmazonServiceException, which means your request made it to Amazon S3, but was rejected with an error response for some reason.");
        LOGGER.error("Error Message:    " + ase.getMessage());
        LOGGER.error("HTTP Status Code: " + ase.getStatusCode());
        LOGGER.error("AWS Error Code:   " + ase.getErrorCode());
        LOGGER.error("Error Type:       " + ase.getErrorType());
        LOGGER.error("Request ID:       " + ase.getRequestId());
    } catch (AmazonClientException ace) {
        LOGGER.error("Caught an AmazonClientException, which means the client encountered an internal error while trying to communicate with S3, such as not being able to access the network.");
        LOGGER.error("Error Message: " + ace.getMessage());
    }
    return result;
}

Other file upload options have easy methods to specify the ACL - just wondering if there is an easier way for the uploadDirectory command

Thanks Damien

回答1:

Going with the solution as described above as unable to come up with an alternative solution



回答2:

You can use an alternative method of TransferManager class:

uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider, ObjectCannedAclProvider cannedAclProvider)

ObjectCannedAclProvider cannedAclProvider = new ObjectCannedAclProvider() {
        public CannedAccessControlList provideObjectCannedAcl(File file) {
                return CannedAccessControlList.PublicRead;
        }
}

MultipleFileUpload multiUpload = transferManager.uploadDirectory(bucketName, keyPrefix, 
              directory, includeSubdirectories, null, null, cannedAclProvider);

The require gradle dependency is : compile("com.amazonaws:aws-java-sdk:1.11.519")

Note: Similar question is asked by someone in the AWS sdk-java thread. https://github.com/aws/aws-sdk-java/issues/1938