欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot项目集成AWS S3,实现上传下载功能

程序员文章站 2022-04-30 23:41:43
...

AWS S3介绍

下面因为使用到的功能很简单,下面会贴出S3的官网链接,有兴趣的同学可以去自行了解详情

AWS S3(官网):  https://www.amazonaws.cn/s3/
AWS SDK for Java(官网): https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/signup-create-iam-user.html

加入相关的pom文件依赖

不同版本的SDK官网描述会有冲突,暂未遇到相关问题,附上pom依赖版本信息, 只是使用了S3的简单功能,实现文件的上传/下载

<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 Java S3-->
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.821</version>
        </dependency>

编码思路

S3作为文件存储服务器,想要与S3交互,类似以阿里云的OSS文件存储服务器,有一个简单的客户端去挑起文件上传,调用S3封装的文件上传API实现文件的上传下载

configClient

springboot配置项目 , 此处不做过多赘述.
yaml文件配置
s3:
service.end.point: localhost:8080
accessKey: accessKey
secretKey: secretKey
bucket.name: /filePath

Amazon S3 配置

    @Value("${biz.s3.service.end.point}")
    public String endPoint;

    @Value("${biz.s3.accessKey}")
    public String accessKey;

    @Value("${biz.s3.secretKey}")
    public String secretKey;
    
    /**
     * 初始化生成AmazonS3 客户端配置
     * @return
     */
    @Bean
    public AmazonS3 s3client() {
        log.info("start create s3Client");
        AwsClientBuilder.EndpointConfiguration endpointConfig =
                new AwsClientBuilder.EndpointConfiguration(endPoint,  Region.getRegion(Regions.CN_NORTH_1).getName());

        AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey,secretKey);
        AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
        ClientConfiguration clientConfig = new ClientConfiguration();
        clientConfig.setProtocol(Protocol.HTTP);

        AmazonS3 S3client = AmazonS3Client.builder()
                .withEndpointConfiguration(endpointConfig)
                .withClientConfiguration(clientConfig)
                .withCredentials(awsCredentialsProvider)
                .disableChunkedEncoding()
                .withPathStyleAccessEnabled(true)
                .withForceGlobalBucketAccessEnabled(true)
                .build();
        log.info("create s3Client success");
        return  S3client;
    }

注意此处有一个比较坑的地方 clientConfig.setProtocol(Protocol.HTTP): 一定要配置S3的客户端的链接协议,如果未配置此项,会出现上传错误问题,此项的配置用于指定向S3服务器发起的请求方式(http/https) , 初次使用的小伙伴很容易踩坑 ,下面附上错误信息,小伙伴可以根据具体的需要去配置不同的传输协议,还可以配置存活/异常链接等等

com.amazonaws.SdkClientException: Unable to execute HTTP request: Unsupported or unrecognized SSL message
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleRetryableException(AmazonHttpClient.java:1207)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1153)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:802)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttmeworkServlet.processRequest(FrameworkServlet.java:1005)
Caused by: javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
	at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(SSLSocketInputRecord.java:439)
	at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:184)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)

上传java实现

此处有一个需要注意的细节.withCannedAcl(CannedAccessControlList.PublicRead)) 配置文件的访问路径,因为我这里想直接通过url访问,又不想写在给文件下载再去提供一个接口, 拼接对应的文件路径,实测可用

    @Value("${biz.s3.bucket.name}")
    public String bucketName;

    @Value("${biz.s3.service.end.point}")
    public String endPoint;
    
    @PostMapping(value = "/testList")
    public Result test(@RequestParam(required = true) MultipartFile file){
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(file.getContentType());
        objectMetadata.setContentLength(file.getSize());
        try {
            String key = System.currentTimeMillis() + file.getOriginalFilename();
            PutObjectResult result = amazonS3.putObject(new PutObjectRequest(bucketName, key , file.getInputStream(), objectMetadata)
                    .withCannedAcl(CannedAccessControlList.PublicRead));   //配置文件访问权限
            //文件访问路径
            String url = endPoint + bucketName + "/" + key;
            System.out.println(url);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.success();
    }

内联此处还有一种方式可以获取文件的访问路径,调用此方法的优点在于,直接拿到key 用户需要下载,可以动态配置访问文件的时间,提高系统的安全性,推荐使用此种方式

    /**
     * 获取文件下载路径
     * @param key 文件的key
     * @return
     */
    private static String downloadFile(String key){
        try {
            if(StringUtils.isEmpty(key)){
                return null;
            }
            GeneratePresignedUrlRequest httpRequest = new GeneratePresignedUrlRequest(BUCKET_NAME, key);
            return s3.generatePresignedUrl(httpRequest).toString();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

至此,简单的上传/下载文件至S3已经完成