当前位置: 首页 > news >正文

Spring Boot 与 Amazon S3:快速上传与下载文件的完整指南

概要

在将 Spring Boot 更新到 3 系列时,由于 javax 需要被替换为 jakarta,因此原先依赖于 javaxspring-cloud-starter-aws1 将无法使用(虽然在我本地环境中仍然可以正常工作)。为了确保兼容性,我将依赖关系更改为 jakartaio.awspring.cloud.spring-cloud-aws-starter,但由于信息较少,特此发布一个示例。

环境

  • Java 17
  • Spring Boot
    • spring-boot-starter-parent:3.2.6
    • spring-cloud-aws-dependencies:3.1.1
    • spring-cloud-aws-starter
    • spring-cloud-aws-starter-s3

示例

以下示例展示了如何将文件(对象)上传到 Amazon S3,并指定存储类为 Intelligent-Tiering。假设从本地环境上传时使用 Intelligent-Tiering,而在 EC2(服务器)环境中上传时使用 Standard(即不指定存储类时的默认值)。

※ 直接相关的部分将被省略。

pom.xml

虽然直接使用 AWS SDK For Java 也是一种选择,但本示例中我们将使用 spring-cloud-aws-starter

<dependencyManagement><dependencies><dependency><groupId>io.awspring.cloud</groupId><artifactId>spring-cloud-aws-dependencies</artifactId><version>3.1.1</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
<dependencies><dependency><groupId>io.awspring.cloud</groupId><artifactId>spring-cloud-aws-starter</artifactId></dependency><dependency><groupId>io.awspring.cloud</groupId><artifactId>spring-cloud-aws-starter-s3</artifactId></dependency>
</dependencies>

dependencyManagement 中指定 spring-cloud-aws-dependencies 可以统一管理版本。

AwsStorageConfig.java

为了在 Service 类中通过 Autowired 使用 S3Client,需要创建一个配置类并将其注册为 Bean。在 EC2 上可以通过 IAM Role 获取认证信息,但在本地环境中无法获取,因此需要显式指定认证信息。

 

package com.tamorieeeen.sample.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
/**** @author rralucard**/
@Configuration
public class AwsStorageConfig {@Value("${spring.cloud.aws.credentials.access-key:unknown}")private String accessKey;@Value("${spring.cloud.aws.credentials.secret-key:unknown}")private String secretKey;@Value("${spring.cloud.aws.region.static:unknown}")private String region;/*** local用*/@Bean("s3Client")@Profile("local")public S3Client s3ClientLocal() {StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey));return S3Client.builder().region(Region.of(region)).credentialsProvider(credentialsProvider).build();}/*** EC2(server)用*/@Bean("s3Client")@Profile("server")public S3Client s3Client() {return S3Client.create();}
}

application.yml

本地使用的 application-local.yml 和 EC2(服务器)使用的 application-server.yml 的配置示例。

本地环境:

spring:cloud:aws:credentials:instance-profile: falseaccess-key: SUMPLEACCESSKEY1234secret-key: SumpleSecretKey123456789stack.auto: falseregion:instance-profile: falsestatic: ap-northeast-1s3:bucket: your-bucket-namestorage-class: INTELLIGENT_TIERING

EC2(Server)用

spring:cloud:aws:credentials:instance-profile: trueuseDefaultAwsCredentialsChain: truestack.auto: falseregion:instance-profile: trues3:bucket: your-bucket-namestorage-class: STANDARD

AwsStorageService.java

上传文件使用 MultipartFile 接收,下载时最终会将文件打包成 ResponseEntity<byte[]> 进行返回。

package com.tamorieeeen.sample.service;import java.io.ByteArrayInputStream;
import java.io.IOException;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;/**** @author rralucard**/
@Service
public class AwsStorageService {@Value("${spring.cloud.aws.s3.bucket}")private String bucket;@Value("${spring.cloud.aws.s3.storage-class}")private String storageClass;@Autowiredprivate S3Client s3Client;/*** 向s3上传文件* @throws IOException* @throws SdkClientException*/public void uploadFile(String s3Path, MultipartFile file) throws SdkClientException, IOException {PutObjectRequest putObjRequest = PutObjectRequest.builder().bucket(bucket).key(s3Path).storageClass(storageClass).contentType(file.getContentType()).contentLength(file.getSize()).build();byte[] bytes = file.getBytes();try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);) {s3Client.putObject(putObjRequest, RequestBody.fromInputStream(inputStream, bytes.length));}}/*** 从S3下载文件* @throws IOException*/public byte[] download(String s3Path) throws IOException {GetObjectRequest getObjRequest = GetObjectRequest.builder().bucket(bucket).key(s3Path).build();try (ResponseInputStream<GetObjectResponse> resInputStream = s3Client.getObject(getObjRequest);) {return resInputStream.readAllBytes();}}
}

官方示例

在解决问题后,我发现了AWS官方提供的示例代码。虽然资料很少,但这份官方样例实际上是AWS SDK for Java的代码示例。

AWS事例

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 从PyTorch官方的一篇教程说开去(4 - Q-table来源及解决问题实例)
  • LeetCode 125.验证回文串 C++写法
  • RDMA通信4:MR(Memory Region, 内存区域)基本概念和作用
  • html改写vue日志
  • 【银河麒麟服务器操作系统】java进程oom现象分析及处理建议
  • 计数,桶与基数排序
  • 建投数据人力资源系列产品获得欧拉操作系统及华为鲲鹏技术认证书
  • vue2 使用代码编辑器插件 vue-codemirror
  • 力扣题解(组合总和IV)
  • spark shell
  • 汽车及零部件研发项目管理系统:一汽东机工选择奥博思 PowerProject 提升研发项目管理效率
  • 人是一个AI Agent吗?
  • React Hook 总结(React 萌新升级打怪中...)
  • python打包exe文件-实现记录
  • Linux下如何安装配置Elastic Stack日志收集系统
  • Angular2开发踩坑系列-生产环境编译
  • Javascript弹出层-初探
  • JAVA并发编程--1.基础概念
  • js数组之filter
  • Kibana配置logstash,报表一体化
  • Mithril.js 入门介绍
  • NSTimer学习笔记
  • Python 基础起步 (十) 什么叫函数?
  • Python进阶细节
  • TypeScript迭代器
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 记一次用 NodeJs 实现模拟登录的思路
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 阿里云移动端播放器高级功能介绍
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • $GOPATH/go.mod exists but should not goland
  • (9)目标检测_SSD的原理
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二)学习JVM —— 垃圾回收机制
  • (离散数学)逻辑连接词
  • (七)c52学习之旅-中断
  • (十六)视图变换 正交投影 透视投影
  • ******之网络***——物理***
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Micro Framework初体验
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .Net下的签名与混淆
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能
  • [8481302]博弈论 斯坦福game theory stanford week 1