一、阿里云OSS对象存储服务介绍
阿里云对象存储OSS(Object Storage Service),是一款海量、安全、低成本、高可靠的云存储服务。使用OSS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。 相当于一个云储存服务器,可以把我们的文件存储到阿里云的服务器中。 在我们使用了阿里云OSS对象存储服务之后,我们的项目当中如果涉及到文件上传这样的业务,在前端进行文件上传并请求到服务端时,在服务器本地磁盘当中就不需要再来存储文件了。我们直接将接收到的文件上传到oss,由oss帮我们存储和管理,同时阿里云的oss存储服务还保障了我们所存储内容的安全可靠。 第三方服务使用的通用思路,我们做一个简单介绍之后,接下来我们就来介绍一下我们当前要使用的阿里云oss对象存储服务具体的使用步骤。Bucket:存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间。 SDK:Software Development Kit 的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK。 简单说,sdk中包含了我们使用第三方云服务时所需要的依赖,以及一些示例代码。我们可以参照sdk所提供的示例代码就可以完成入门程序。
二、服务开通与使用准备
1、准备工作
注册阿里云账户(注册完成后需要实名认证),注册完账号之后登录阿里云https://www.aliyun.com/。
产品搜索OSS,点击进入对象存储OSS。2、开通OSS云服务(新用户免费使用三个月)
进入后点击免费试用。(如果不是新用户,之前已开通过OSS服务,请使用充值渠道获取该服务)
找到对象存储OSS,点击立即试用。
3、创建存储空间bucket
存储空间(Bucket)是用于存储对象(Object)的容器。在上传任意类型的Object前,您需要先创建Bucket。在阿里云工作台中搜搜OSS,进入对象存储OSS的管理控制台:https://oss.console.aliyun.com/overview
在左侧导航栏中,点击Bucket列表,然后点击创建Bucket。填写bucket名称,名字唯一不能与其他用户的bucket重复。
Bucket 命名规范
命名长度为 3~63 个字符
只允许小写字母、数字、短横线(-),且不能以短横线开头或结尾
Bucket 名称在 OSS 范围内必须全局唯一
注意读写权限这里要选择公共读!如果选择私有,只是自己能上传,其他用户无法访问。其他选项保持默认即可。
点击确认创建。
创建成功,点击进入bucket。
这里可以看到bucket的概览信息,记住自己的bucketName和Endpoint,后面代码中调用第三方服务会用到。
4、创建并保存Accesskey
在阿里云网站上的个人中心配置Accesskey,查询AccessKeyld和AccesskeySecret。
点击继续使用AccessKey。
点击创建AccessKey。
注意:通过安全验证后可以看到生成的accessKeyld和accessKeySecret,大家下载csv文件或者复制下来,因为accessKeySecret只显示一次,点击确定后将不再显示!
5、配置访问凭证AK & SK(系统环境变量)
目前最新官方SDK要求将AccessKey ID和AccessKey Secret配置到系统环境变量,才能使用阿里云OSS服务。
- 以Windows配置访问凭证为例(其他系统请参考官方文档)
set ALIBABA_CLOUD_ACCESS_KEY_ID=yourAccessKeyId
set ALIBABA_CLOUD_ACCESS_KEY_SECRET=yourAccessKeySecret
执行如下命令,让更改生效。注意:将上述的ACCESS_KEY_ID 与 ACCESS_KEY_SECRET 的值要替换成自己的。
setx ALIBABA_CLOUD_ACCESS_KEY_ID "%ALIBABA_CLOUD_ACCESS_KEY_ID%"
setx ALIBABA_CLOUD_ACCESS_KEY_SECRET "%ALIBABA_CLOUD_ACCESS_KEY_SECRET%"
执行如下命令,验证环境变量是否生效。
echo %ALIBABA_CLOUD_ACCESS_KEY_ID%
echo %ALIBABA_CLOUD_ACCESS_KEY_SECRET%
注意:设置完环境变量需要重启IDEA,才能重新读取系统环境变量。
三、阿里云OSS使用步骤
阿里云OSS对象存储服务的准备工作我们已经完成了,接下来我们参照官方所提供的SDK示例来编写入门程序。 首先我们需要来打开 阿里云OSS的官方文档 ,在官方文档中找到 SDK 的示例代码:1、导入依赖坐标
以Java安装SDK为例,通过Maven引入阿里云OSS的依赖。
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
如果使用的是Java 9及以上的版本,则需要添加JAXB相关依赖。添加JAXB相关依赖示例代码如下:
<!-- Java 9及以上的版本还需引入以下三个依赖 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
2、文件上传Demo快速入门
找到官方SDK文档的上传文件流代码,点击复制。
这里主要修改地域节点endpoint
、存储空间名称bucketName
、要上传到存储空间的文件路径objectName
,要上传的本地文件完整路径filePath
,根据自己的配置,修改为自己的。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.FileInputStream;
import java.io.InputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "oss-bucket-web";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "oss-test/略显智慧的表情.jpg";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "D:\\图片\\QQ截图\\略显智慧的表情.jpg";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
执行main方法,可以发现bucket中已经自动创建文件夹,文件上传成功。
点击上传的文件,这个URL就是文件通过OSS生成的访问下载地址。
3、阿里云OSS工具类
根据官方的文件上传Demo,我们可以抽取成一个文件上传工具类,方便我们上传文件调用。
- 阿里云OSS文件上传工具类AliOSSUtils,可直接复制粘贴使用(注意修改自己的OSS四项配置信息)。
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* 阿里云OSS文件上传工具类
*/
@Component
public class AliOSSUtils {
// 将以下四项替换为自己的信息
private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
private String accessKeyId = "yourAccessKeyId";
private String accessKeySecret = "yourAccessKeySecret";
private String bucketName = "oss-bucket-web";
/**
* 实现上传文件到OSS,上传的文件对象以UUID命名,并返回文件访问路径
* 方法重载,直接以UUID文件名存储,无上传目录
* @param multipartFile Spring接收前端上传文件的对象
* @return 对象存储在OSS中的URL
* @throws IOException
*/
public String upload(MultipartFile multipartFile) throws IOException {
return upload(multipartFile, ""); // 把上传到oss的路径返回
}
/**
* 实现上传文件到OSS,上传的文件对象以UUID命名,并返回文件访问路径
* OSS存储文件路径为:uploadDir/UUID.文件后缀名
* @param multipartFile Spring接收前端上传文件的对象
* @param uploadDir 上传文件到OSS的目录,不能包含Bucket名称,只能包含目录,不能以“/”开头,目录可传参为空。
* @return 对象存储在OSS中的URL
* @throws IOException
*/
public String upload(MultipartFile multipartFile, String uploadDir) throws IOException {
// 判断上传目录是否为空,不为空则进行目录合法性校验
if (uploadDir == null || "/".equals(uploadDir)) return upload(multipartFile);
uploadDir = uploadDir.trim();
if (uploadDir.startsWith("/")) uploadDir = uploadDir.substring(1);
if (!"".equals(uploadDir) && !uploadDir.endsWith("/")) uploadDir += "/";
// 获取上传的文件的输入流
InputStream inputStream = multipartFile.getInputStream();
// 获取上传文件的原始文件名
String originalFilename = multipartFile.getOriginalFilename();
// 为保证文件名唯一,避免文件上传覆盖,使用UUID作为文件名,并拼接文件后缀名
String fileName = uploadDir + UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 上传文件到 OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, inputStream);
// 文件访问路径 = https://bucketName.endpoint/fileName,例如https://oss-bucket-web.oss-cn-beijing.aliyuncs.com/uploadDir/UUID.jpg
String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
// 关闭ossClient
ossClient.shutdown();
// 把上传到oss的路径返回
return url;
}
}
- 文件上传控制器UploadController,模拟文件上传服务。
import com.dkd.common.utils.file.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/upload")
@Slf4j
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
@PostMapping("/oss")
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
if (file.isEmpty()) {
log.warn("上传文件为空");
return "上传文件为空,未接收到文件";
}
// 上传到根目录
String url = aliOSSUtils.upload(file);
// 上传到指定目录
//String url = aliOSSUtils.upload(file, "uploads");
log.info("文件上传成功,访问地址为:{}", url);
return url;
}
}
- 使用Apifox或Postman发送文件上传的Post请求
工具类成功返回文件上传到OSS可供访问下载的URL。
4、工具类解耦优化
- 优化一:用@Value注解配置常量抽取到properties或yml文件中,防止在程序中硬编码,降低耦合度。
- 优化二:使用官方推荐的EnvironmentVariableCredentialsProvider对象来创建OSS对象,accessKeyId和accessKeySecret从系统环境变量中获取,提升安全性。
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.UUID;
/**
* 阿里云OSS文件上传工具类
*/
@Component
public class AliOSSUtils {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
/**
* 实现上传文件到OSS,上传的文件对象以UUID命名,并返回文件访问路径
* 方法重载,直接以UUID文件名存储,无上传目录
* @param multipartFile Spring接收前端上传文件的对象
* @return 对象存储在OSS中的URL
* @throws Exception
*/
public String upload(MultipartFile multipartFile) throws Exception {
return upload(multipartFile, ""); // 把上传到oss的路径返回
}
/**
* 实现上传文件到OSS,上传的文件对象以UUID命名,并返回文件访问路径
* OSS存储文件路径为:uploadDir/UUID.文件后缀名
* @param multipartFile Spring接收前端上传文件的对象
* @param uploadDir 上传文件到OSS的目录,不能包含Bucket名称,只能包含目录,不能以“/”开头,目录可传参为空。
* @return 对象存储在OSS中的URL
* @throws Exception
*/
public String upload(MultipartFile multipartFile, String uploadDir) throws Exception {
// 判断上传目录是否为空,不为空则进行目录合法性校验
if (uploadDir == null || "/".equals(uploadDir)) return upload(multipartFile);
uploadDir = uploadDir.trim();
if (uploadDir.startsWith("/")) uploadDir = uploadDir.substring(1);
if (!"".equals(uploadDir) && !uploadDir.endsWith("/")) uploadDir += "/";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 获取上传的文件的输入流
InputStream inputStream = multipartFile.getInputStream();
// 获取上传文件的原始文件名
String originalFilename = multipartFile.getOriginalFilename();
// 为保证文件名唯一,避免文件上传覆盖,使用UUID作为文件名,并拼接文件后缀名
String fileName = uploadDir + UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 创建OSSClient实例,上传文件到OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
ossClient.putObject(bucketName, fileName, inputStream);
// 文件访问路径 = https://bucketName.endpoint/fileName,例如https://oss-bucket-web.oss-cn-beijing.aliyuncs.com/uploadDir/UUID.jpg
if (!endpoint.startsWith("https://")) endpoint = "https://" + endpoint;
String[] endpointPart = endpoint.split("//");
StringBuilder url = new StringBuilder(endpointPart[0]); // https:
url.append("//")
.append(bucketName)
.append(".")
.append(endpointPart[1])
.append("/")
.append(fileName);
// 关闭ossClient
ossClient.shutdown();
// 把上传到oss的路径返回
return url.toString();
}
}
- application.properties 或 application.yml中的配置:
# application.properties
aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
aliyun.oss.bucketName=oss-bucket-web
# application.yaml
# 阿里云OSS配置
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: oss-bucket-web
- 将测试的Controller中的上传代码,改为上传到uploads文件夹下(第二个参数为上传到OSS的存储文件夹)。
// 上传到指定目录
String url = aliOSSUtils.upload(file, "uploads");
- 通过Apifox发送Post请求,注意请求参数名称指定为file,提交类型指定为form-data。
- 阿里云OSS控制台成功存储,并自动创建了uploads文件夹,文件上传成功!
四、阿里云OSS自定义starter
1、需求说明
背景:假设项目组里不止一人用到阿里云OSS工具类,开发团队想要引入依赖就能使用工具类,后期工具类有新增功能时,方便统一修改管理。
需求:自定义aliyun-oss-spring-boot-starter,完成阿里云OSS操作工具类 AliOSSUtils 的自动配置。
目标:引入起步依赖引入之后,要想使用阿里云OSS,注入AliOSSUtils直接使用即可。
2、步骤分析
(1)创建 aliyun-oss-spring-boot-starter 模块。
(2)创建 aliyun-oss-spring-boot-autoconfigure 模块,在starter中到引入该模块。
(3)在 aliyun-oss-spring-boot-autoconfigure 模块中的定义自动配置功能,并定义自动配置文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。
3、自定义starter实现
(1)创建starter模块
将starter模块中多余的文件全部删掉。
(2)创建autoconfigure模块
(3)在starter的pom中引入autoconfigure的依赖
配置starter的pom文件:
- 引入spring-boot-starter核心起步依赖,用于实现SpringBoot自动配置。
- 引入阿里云OSS的自动配置类aliyun-oss-spring-boot-autoconfigure,用于完成AliOSSUtils的自动装配。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- springboot核心起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 阿里云OSS的自动配置类 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
(4)配置autoconfigure的pom
配置autoconfigure的pom文件:
- 引入spring-boot-starter核心起步依赖,用于实现SpringBoot自动配置。
- 引入spring-web,接收上传文件的MultipartFile类需要用到。
- 引入阿里云OSS的相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- springboot核心起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring-web MultipartFile需要 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
<!-- Java 9及以上的版本还需引入以下三个依赖 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
</project>
(5)创建AliOSSUtils、AliOSSProperties、AliOSSAutoConfiguration类
- 文件上传工具类AliOSSUtils,将工具类再次升级改造为从AliOSSProperties中读取配置信息。同时去掉@Component注解,因为我们的启动类不会去扫描com.aliyun.oss包。
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.UUID;
/**
* 阿里云OSS文件上传工具类
*/
public class AliOSSUtils {
private AliOSSProperties aliOSSProperties;
public AliOSSProperties getAliOSSProperties() {
return aliOSSProperties;
}
public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
this.aliOSSProperties = aliOSSProperties;
}
/**
* 实现上传文件到OSS,上传的文件对象以UUID命名,并返回文件访问路径
* 方法重载,直接以UUID文件名存储,无上传目录
* @param multipartFile Spring接收前端上传文件的对象
* @return 对象存储在OSS中的URL
* @throws Exception
*/
public String upload(MultipartFile multipartFile) throws Exception {
return upload(multipartFile, ""); // 把上传到oss的路径返回
}
/**
* 实现上传文件到OSS,上传的文件对象以UUID命名,并返回文件访问路径
* OSS存储文件路径为:uploadDir/UUID.文件后缀名
* @param multipartFile Spring接收前端上传文件的对象
* @param uploadDir 上传文件到OSS的目录,不能包含Bucket名称,只能包含目录,不能以“/”开头,目录可传参为空。
* @return 对象存储在OSS中的URL
* @throws Exception
*/
public String upload(MultipartFile multipartFile, String uploadDir) throws Exception {
// 判断上传目录是否为空,不为空则进行目录合法性校验
if (uploadDir == null || "/".equals(uploadDir)) return upload(multipartFile);
uploadDir = uploadDir.trim();
if (uploadDir.startsWith("/")) uploadDir = uploadDir.substring(1);
if (!"".equals(uploadDir) && !uploadDir.endsWith("/")) uploadDir += "/";
// 获取上传文件的原始文件名
String originalFilename = multipartFile.getOriginalFilename();
// 为保证文件名唯一,避免文件上传覆盖,使用UUID作为文件名,并拼接文件后缀名
String fileName = uploadDir + UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 获取上传的文件的输入流
InputStream inputStream = multipartFile.getInputStream();
// 从AliOSSProperties中获取endpoint和bucketName
String endpoint = aliOSSProperties.getEndpoint();
String bucketName = aliOSSProperties.getBucketName();
// 创建OSSClient实例,上传文件到OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
ossClient.putObject(bucketName, fileName, inputStream);
// 文件访问路径 = https://bucketName.endpoint/fileName,例如https://oss-bucket-web.oss-cn-beijing.aliyuncs.com/uploadDir/UUID.jpg
if (!endpoint.startsWith("https://")) endpoint = "https://" + endpoint;
String[] endpointPart = endpoint.split("//");
StringBuilder url = new StringBuilder(endpointPart[0]); // https:
url.append("//")
.append(bucketName)
.append(".")
.append(endpointPart[1])
.append("/")
.append(fileName);
// 关闭ossClient
ossClient.shutdown();
// 把上传到oss的路径返回
return url.toString();
}
}
- 阿里云OSS配置类AliOSSProperties,用于从引入该starter的模块下读取配置文件中前缀为aliyun.oss的配置项。注意endpoint和bucketName属性名要与配置文件中前缀下的key保持一致,同时需要提供get和set方法。
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "aliyun.oss") // 从引入该starter的模块下的配置文件中读取,prefix为配置前缀
public class AliOSSProperties {
// 前缀下的配置项的key要与属性名保持一致
private String endpoint;
private String bucketName;
// 需要添加get和set方法
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
}
@ConfigurationProperties和@Value的区别相同点:都是用来注入外部配置的属性的。
不同点:
- @Value注解只能一个一个的进行外部属性的注入(属性多的情况下注入很麻烦)。
- @ConfigurationProperties可以批量的将外部的属性配置注入到bean对象的属性中(前缀可以复用)。
@ConfigurationProperties使用注意点:
- 需要创建一个实现类,且实体类中的属性名和配置文件当中key的名字必须要一致。
- 实体类中的属性还需要提供getter和setter方法。
- 阿里云OSS自动配置类AliOSSAutoConfiguration,用于将工具类注册为Spring的bean对象,并设置配置类。@EnableConfigurationProperties可以将配置类AliOSSProperties直接注册为bean对象,从而我们可以从Spring的容器中去获取配置好的AliOSSProperties对象。
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(AliOSSProperties.class)
public class AliOSSAutoConfiguration {
@Bean
public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties) {
AliOSSUtils aliOSSUtils = new AliOSSUtils();
aliOSSUtils.setAliOSSProperties(aliOSSProperties);
return aliOSSUtils;
}
}
(6)创建.imports自动配置文件
在resources资源路径下创建文件夹META-INF/spring,在这个文件夹下创建名为org.springframework.boot.autoconfigure.AutoConfiguration.imports的自动配置文件,供SpringBoot底层的自动配置去扫描读取。文件目录结构如下图所示:
4、测试阿里云OSS的自定义starter
准备一个测试模块
在测试模块的pom中引入阿里云OSS的自定义starter依赖和web依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aizen</groupId>
<artifactId>springboot-autoconfiguration-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在yaml文件中配置阿里云OSS的配置项:
# 阿里云OSS配置
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: oss-bucket-web
测试文件上传UploadController,AliOSSUtils工具类将通过自动配置后自动注入:
import com.aliyun.oss.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/upload")
@Slf4j
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
@PostMapping("/oss")
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
if (file.isEmpty()) {
log.warn("上传文件为空");
return "上传文件为空,未接收到文件";
}
// 上传到根目录
String url = aliOSSUtils.upload(file);
log.info("文件上传成功,访问地址为:{}", url);
return url;
}
}
通过Apifox发送文件上传的Post请求,成功响应存储url。
使用阿里云OSS自定义starter文件上传成功!