简单记录一下在Springboot中上传文件到AWS S3存储服务的代码。
在application.xml中添加aws相关配置:
| 
					 1 2 3 4 5 6  | 
						custom:   aws:     access-key: CHOBITACCESSKEY     secret-key: CHOBIT/THISIS006SECRET007Key/dotORG     bucket: zhyea     endpoint: www.zhyea.com:80  | 
					
新建一个AwsS3Componment类来执行上传文件操作:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33  | 
						@Component public class AwsS3Component implements InitializingBean {     @Value("${custom.aws.access-key}")     private String accessKey;     @Value("${custom.aws.secret-key}")     private String accessSecret;     @Value("${custom.aws.bucket}")     private String bucket;     @Value("${custom.aws.endpoint}")     private String endpoint;     private AmazonS3 client;     @Override     public void afterPropertiesSet() {         ClientConfiguration config = new ClientConfiguration();         config.setProtocol(Protocol.HTTP);         config.disableSocketProxy();         this.client = AmazonS3ClientBuilder                 .standard()                 .withClientConfiguration(config)                 .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, accessSecret)))                 .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, Regions.CN_NORTH_1.getName()))                 .enablePathStyleAccess()                 .build();     } }  | 
					
因为使用的服务有设置endpoint,所以这里需要使用下面这一行完成endpoint的设置:
| 
					 1  | 
						withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, Regions.CN_NORTH_1.getName()))  | 
					
如果不设置endpoint就会收到下面这样的报错:
| 
					 1 2 3 4 5 6 7  | 
						com.amazonaws.services.s3.model.AmazonS3Exception: The AWS Access Key Id you provided does not exist in our records. (Service: Amazon S3; Status Code: 403; Error Code: InvalidAccessKeyId; Request ID: FRDT8N0RAQFNCVDP; S3 Extended Request ID: DemEatwroXry2YN/5lyuMKDmhIi/aIz3QZPmLN0DYHeHU3oGUeOClJBcToz1J1qkcBZBfklRNs8=) 	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1660) 	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1324) 	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1074) 	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:745) 	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:719) 	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:701)  | 
					
异常信息中提示了AccessKey无效——虽然我的AccessKey是有效的。
在endpoint的这行配置中还设置了region信息。如果不需要设置endpoint,就得补上region的配置:
| 
					 1 2 3 4 5 6 7  | 
						this.client = AmazonS3ClientBuilder         .standard()         .withClientConfiguration(config)         .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, accessSecret)))         .withRegion(Regions.CN_NORTH_1) //Region配置         .enablePathStyleAccess()         .build();  | 
					
下面是执行上传的代码:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13  | 
						/**  * 执行文件上传  *  * @param file 要上传的文件的路径  * @param key  存储文件的路径  * @return 文件路径  */ private String upload(File file, String key) {     client.putObject(new PutObjectRequest(bucket, key, file).withCannedAcl(CannedAccessControlList.PublicRead));     GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucket, key);     URL url = client.generatePresignedUrl(urlRequest);     return url.toString(); }  | 
					
这里是通过File实例执行的上传。有时候会需要直接通过文件流执行上传,此时可以使用下面的代码:
| 
					 1 2 3 4 5 6 7 8 9 10 11  | 
						private String upload(InputStream input, String key) throws IOException {     Date expireDate = new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30));     ObjectMetadata metadata = new ObjectMetadata();     metadata.setHttpExpiresDate(expireDate);     metadata.setContentLength(input.available());     client.putObject(new PutObjectRequest(bucket, key, input, metadata).withCannedAcl(CannedAccessControlList.PublicRead));     GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucket, key);     URL url = client.generatePresignedUrl(urlRequest);     return url.toString(); }  | 
					
注意这里的setContentLength()最好配置一下。不设置会在处理的时候给出WARN。根据方法文档也可以看到,如果不设置,在上传的时候就会先在内存中缓存整个信息流来计算文件长度。
大体上就是这样了。
End!
发表评论