使用AWS SDK for Java 上传和下载文件。 已有 amazonaws.cn 中国区账号。
本文叙述了怎样获取访问密钥,进行demo配置,demo运行出错的解决办法。
登录 https://console.amazonaws.cn/iam/home,点击左侧“用户”,选择自己的账号;点击“安全证书”,可以看到下方有访问密钥,我的账号只能申请2个密钥,之前的key已经不知道了,删掉旧的申请个新的即可。得到的就是aws_access_key_id 和 aws_secret_access_key 。
参考文章 http://docs.aws.amazon.com/zh_cn/sdk-for-java/v1/developer-guide/setup-credentials.html,在本地系统上的 AWS 凭证配置文件中设置凭证,该配置文件位于:
~/.aws/credentials (在 Linux、macOS 或 Unix) 上
C:\Users\USERNAME\.aws\credentials (在 Windows 上)
文件包含以下格式的行,用自己的 AWS 凭证值替换值 your_access_key_id 和 your_secret_access_key。
[default]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key
AmazonS3 的初始化
AmazonS3 s3client = new AmazonS3Client(new ProfileCredentialsProvider());
官方文档中给出的密钥配置方式需要在特定目录下放置配置文件,工程部署不方便。找了参数方式初始化的方法。
AWSCredentials credentials = new BasicAWSCredentials(
myConfig.AWS_ACCESS_KEY_ID, myConfig.AWS_SECRET_ACCESS_KEY);
AmazonS3 s3Client = new AmazonS3Client(credentials);
参考官方文档
http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/UploadObjSingleOpJava.html,
在自己的工程里新建了UploadObjectSingleOperation类,需要配置的三项如下:
private static String bucketName = "手动在AWS S3中创建的桶名称";
private static String keyName = "希望这个文件上传后的key,需要注意的,这个key不要重复,否则会覆盖掉旧的文件";
private static String uploadFileName = "待上传的本地文件路径和名称";
依赖包(gradle)
// https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3
compile group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.238'
java.lang.reflect.InvocationTargetException: null
……
Caused by: org.apache.http.conn.ConnectTimeoutException: Connect to englishresourcebucket.s3.amazonaws.com:443 [englishresourcebucket.s3.amazonaws.com/54.231.33.147] failed: Read timed out
……
Caused by: java.net.SocketTimeoutException: Read timed out
解决办法,设置区域:
String regionName = "cn-north-1";
Region region = Region.getRegion(Regions.fromName(regionName));
s3client.setRegion(region);
String serviceEndpoint = region.getServiceEndpoint(ServiceAbbreviations.S3);
s3client.setEndpoint(serviceEndpoint);
s3client.putObject(new PutObjectRequest(bucketName, keyName, file));
参考官方文档,
http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/GettingObjectsUsingAPIs.html
http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/RetrievingObjectUsingJava.html GetObject.java
同样的也加上区域设置的代码,就可以跑通这段demo了。
private AmazonS3 s3Client;
private String bucketName;
public S3Service(MyConfig myConfig) {
AWSCredentials credentials = new BasicAWSCredentials(
myConfig.AWS_ACCESS_KEY_ID, myConfig.AWS_SECRET_ACCESS_KEY);
s3Client = new AmazonS3Client(credentials);
String regionName = myConfig.AWS_REGION;
Region region = Region.getRegion(Regions.fromName(regionName));
s3Client.setRegion(region);
final String serviceEndpoint = region.getServiceEndpoint(ServiceAbbreviations.S3);
s3Client.setEndpoint(serviceEndpoint);
bucketName = myConfig.AWS_BUCKET_NAME;
}
public void upload(MultipartFile file, String keyName)
throws MyException {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
metadata.setContentLength(file.getSize());
try {
s3Client.putObject(new PutObjectRequest(
bucketName, keyName, file.getInputStream(), metadata));
} catch (AmazonServiceException ase) {
logger.warn("Caught an AmazonServiceException, which " +
"means your request made it " +
"to Amazon S3, but was rejected with an error response" +
" for some reason.");
logger.warn(printAse(ase));
throw new MyException ("upload file failed",
MyExceptionType.AWS_UPLOAD_FAILED);
} catch (AmazonClientException ace) {
logger.warn("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.warn("Error Message: " + ace.getMessage());
throw new MyException ("upload file failed",
MyExceptionType.AWS_UPLOAD_FAILED);
} catch (IOException ioe) {
logger.warn("Caught an IOException: " + ioe.getMessage());
throw new MyException ("upload file failed",
MyExceptionType.AWS_UPLOAD_FAILED);
}
}