pom.xml
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.336</version>
</dependency>
nacos配置自定义参数
aws:
s3:
access-key-id: *****
secret-key: *****
bucket: ****
region: ap-east-1
@Setter
@Getter
@Component
@ConfigurationProperties(prefix = "aws.s3")
public class AwsS3Properties {
@ApiModelProperty("accessKeyId")
private String accessKeyId;
@ApiModelProperty("secretKey")
private String secretKey;
@ApiModelProperty("储存桶名称")
private String bucket;
@ApiModelProperty("地区")
private String region;
}
sevice实现
@Autowired
private AwsS3Properties awsS3Properties;
/**
* @param Key 文件唯一名称
* @param file 文件
* @return 文件地址
*/
@Override
public String uploadToS3(String Key, MultipartFile file) {
// 通过 accessKeyId、secretKey 生成认证的aws凭证对象
BasicAWSCredentials credentials = new BasicAWSCredentials(awsS3Properties.getAccessKeyId(), awsS3Properties.getSecretKey());
// 通过凭证对象 awsCredentials 跟 区域 region 生成s3的服务端(ap-east-1亚太地区香港的区域)
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withRegion(awsS3Properties.getRegion())
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
// 设置文件元数据
// contentType: 默认不设置的话是什么ostream什么之类的访问链接的话就会下载文件
ObjectMetadata metadata = new ObjectMetadata();
// metadata.setContentType(file.getContentType());
metadata.setContentLength(file.getSize());
try {
// 想要通过公网访问到图片,除了将桶的权限更改之外,还需要设置withCannedAcl(CannedAccessControlList.PublicRead)
PutObjectRequest putObjectRequest = new PutObjectRequest(
awsS3Properties.getBucket(), Key, file.getInputStream(), metadata)
.withCannedAcl(CannedAccessControlList.PublicRead);
s3.putObject(putObjectRequest);
} catch (IOException e) {
log.error(String.format("Upload file [%s] to AWS S3 failed! Error: %s", Key, e.getMessage()));
} finally {
s3.shutdown();
}
return s3.getUrl(awsS3Properties.getBucket(), Key).toString();
}
注意:S3的储存桶权限默认是阻止公众访问的,也就是说上传图片后返回的地址都是预签名URL并且最长时间7天。
解决方案(当前业务代码为第二种方案)
1 :前端实时返显时需要每次拿桶(bucket)和文件名称预签名一下参考方案
2 :需要开放桶权限,后端代码uploadToS3S对象时设置对象ACL(public-read)。以后URL直接存数据库里,URL没有签名也没有时间限制,直接拿来用就行