#java #amazon-web-services #spring-boot #amazon-s3
Вопрос:
Я пытаюсь загрузить файл в Amazon S3. Он отлично работает в моем локальном, но я получаю ошибку «отказано в разрешении» во время его развертывания в Elastic Beanstalk.
Мой код:
public String uploadFileToS3BucketTemp(ByteArrayOutputStream baos, boolean enablePublicReadAccess, String filename, String path)
{
LocalDateTime localDate = LocalDateTime.now();
String currentDateTime = CommonFunctions.customDateFormatter(CommonFunctions.getCurrentDateTime(), "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd");
Date date = new Date();
//Pattern for showing milliseconds in the time "SSS"
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
String str = sdf.format(date);
String time = str.split("\s")[1].split("\.")[0];
String currentTime = time.replaceAll(":", "-");
String fileName = filename "-" currentDateTime "-" currentTime ".xls";
String filePath = "";
try {
File file = new File(filePath fileName);
FileOutputStream fos = new FileOutputStream(file);
baos.writeTo(fos);
fos.close();
InputStream is=new FileInputStream(file);
s3Client.putObject(new PutObjectRequest(bucketName, path "/" fileName, is, new ObjectMetadata()));
} catch (IOException | AmazonServiceException ex) {
logger.error("error [" ex.getMessage() "] occurred while uploading [" fileName "] ");
}
String url = signedUrl(path "/" fileName);
return url;
}
При проверке журналов сервера он показывает мне следующую ошибку:
ERROR 25491 (Permission denied)] occurred while uploading
Ведро не является общедоступным. У ElasticBeantsalk есть роль IAM, которая имеет разрешение AmazonS3FullAccess
Комментарии:
1. Покажите код, в котором вы создаете
s3Client
2. Не могли бы вы показать нам полис на ведре. Иногда это может относиться к спискам управления доступом
Ответ №1:
«Я получаю ошибку»Отказано в разрешении», когда он развернут в эластичном бобовом стебле».
Вы можете сослаться на примеры AWS, в которых описывается, как загрузить данный файл с рабочего стола в корзину Amazon S3 с помощью веб-приложения, написанного на Java. Поскольку используется Java (приложение для весенней загрузки), вы можете использовать AWS SDK для Java V2.
Создание примера приложения AWS photo analyzer с использованием пакета SDK AWS для Java
В этом примере обратите внимание, что приложение развернуто в Elastic Beanstalk. Клиент службы Amazon S3 создается следующим образом:
S3Client s3 = S3Client.builder()
.credentialsProvider(EnvironmentVariableCredentialsProvider.create())
.region(region)
.build();
В Elastic Beanstalk вы можете установить для своих учетных записей роль IAM с разрешениями Amazon S3, определив эти переменные:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
Теперь вы можете использовать клиент службы S3 для размещения файла в корзине Amazon S3, используя эту логику Java:
// Places an image into a S3 bucket.
public String putObject(byte[] data, String bucketName, String objectKey) {
s3 = getClient();
try {
PutObjectResponse response = s3.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(objectKey)
.build(),
RequestBody.fromBytes(data));
return response.eTag();
} catch (S3Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
return "";
}
Ответ №2:
Вы можете построить AmazonS3
объект для того, чтобы вызвать вызов API putObject()
. Есть два способа,
—> Вы можете предоставить учетные данные и построить > AmazonS3
(Не рекомендуется для развертывания в облаке)
AWSCredentials awsCredentials = new BasicAWSCredentials(aws_access_key, aws_secret_key);
return AmazonS3ClientBuilder
.standard()
.withRegion("ap-south-1")
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
—> Вы можете предоставить учетные данные через > AWS IAM
роль. (Рекомендуется)
InstanceProfileCredentialsProvider provider = new InstanceProfileCredentialsProvider(true);
return AmazonS3ClientBuilder.standard()
.withCredentials(provider)
.build();
Предполагается, что вы должны предоставить соответствующее разрешение для S3. (в этом примере для вызова putObject()
)
—> > putObject()
Вызов API будет выглядеть так, как показано ниже в блоке кода.
public void upload(String thePath, String theFileName, Optional<Map<String, String>> theOptionalMetaData,
InputStream inputStream) {
printLog("upload(): Executed with path - " thePath " and file name - " theFileName);
ObjectMetadata objectMetadata = new ObjectMetadata();
theOptionalMetaData.ifPresent(map -> {
//Loops through the optionalMetaData map adding all of the file information to the S3 objectMetaData.
if (!map.isEmpty()) {
map.forEach(objectMetadata::addUserMetadata);
}
});
printLog("upload(): Done adding metadata");
try {
//Saves the file to Amazon S3 bucket
amazonS3.putObject(thePath, theFileName, inputStream, objectMetadata);
}
catch (AmazonServiceException exception) {
printLog("upload(): Exception upon uploading file");
throw new IllegalStateException("Exception upon uploading file", exception);
}
printLog("upload(): File upload successful");
}
Надеюсь, этот пост поможет вам продолжить, счастливого кодирования!
Ответ №3:
Я бы рекомендовал вам проверить свой профиль экземпляра ec2 и политику корзины s3.
Убедитесь, что профиль экземпляра имеет доступ к S3, а политика корзины S3 разрешает объекты, помещенные из профиля экземпляра.
https://aws.amazon.com/premiumsupport/knowledge-center/elastic-beanstalk-s3-bucket-instance/