引入依赖
在qk-common模块的pom.xml引入下面的依赖,其中版本锁定需要在父模块中完成,此处不再赘述。
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.18.4</version>
</dependency>
<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>配置访问凭证
在CMD中运行以下命令 , 需要注意其中的YOUR_ACCESS_KEY_ID 和YOUR_ACCESS_KEY_SECRET要换成自己申请的密钥
setx OSS_ACCESS_KEY_ID "YOUR_ACCESS_KEY_ID"
setx OSS_ACCESS_KEY_SECRET "YOUR_ACCESS_KEY_SECRET"运行以下命令,检查环境变量是否生效。
echo %OSS_ACCESS_KEY_ID%
echo %OSS_ACCESS_KEY_SECRET%也可以在系统的环境变量中配置,需要重启下系统。
编写测试代码
在qk-common的test目录下新建com.cghbh包,创建下面的配置文件,直接在com.cghbh目录下粘贴可以快速创建整个文件。
package com.cghbh;
import com.aliyun.oss.ClientBuilderConfiguration;
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 com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.FileInputStream;
import java.io.InputStream;
public class AliyunOssTest {
public static void main(String[] args) throws Exception {
String xxx = System.getenv("xxx");
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-shanghai.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量 OSS_ACCESS_KEY_ID 和 OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "heima-qkxxx";
// 指的是文件上传到阿里云OSS存储的文件名称。
String objectName = "zuoxishijian1.jpg";
// 填写本地文件的完整路径
String filePath = "C:\\Users\\gchen\\Desktop\\zuoxishijian.jpg";
// 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
String region = "cn-shanghai";
// 创建OSSClient实例。
// 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// 读取本地文件的流数据(二进制数据)
// 读取磁盘文件 : InputStream(输入流) OutputStream(输出流)
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (Exception oe) {
oe.printStackTrace();
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}提取为工具类
自定义配置读取
注意 : qk-common 模块中需要通过SpringBoot注解读取配置文件信息,需要额外添加一个依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>修改application.yml配置文件, 添加阿里云OSS相关配置。
自定义配置如何读取
SpringBoot项目中读取自定义信息的方式有两种
- 在属性上使用
@Value("${``aliyun.oss.endpoint``}")注解的方式一个个读取配置 - 使用
@ConfigurationProperties(``prefix='配置前缀'``)注解批量读取自定义配置
使用方案1获取配置的代码如下(在qk-common包中创建OssTemplate文件):
package com.cghbh.util;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
public class OssTemplate {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
@Value("${aliyun.oss.region}")
private String region;
}使用方案2获取配置的代码如下(在qk-common包中创建OssTemplate文件):
package com.cghbh.util;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOssProperties {
private String endpoint;
private String bucketName;
private String region;
}在qk-management的application.yml增加的alioss配置如下:
# 阿里云oss配置
aliyun:
oss:
endpoint: https://oss-cn-shanghai.aliyuncs.com
bucketName: heima-qkxxx
region: cn-shanghai功能封装
为了方便后续程序的扩展和维护,我们需要对阿里云oss进行工具的封装。在qk-common模块中创建com.cghbh.util包,然后创建OssTemplate 类(修改测试程序,封装成工具类如下):
package com.cghbh.util;
import cn.hutool.core.lang.UUID;
import com.aliyun.oss.ClientBuilderConfiguration;
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 com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.PutObjectRequest;
import com.cghbh.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Slf4j
@Component
public class OssTemplate {
@Autowired
private AliyunOssProperties aliyunOssProperties;
public String upload(String fileName, InputStream inputStream) {
OSS ossClient = null;
try {
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量 OSS_ACCESS_KEY_ID 和 OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 创建OSSClient实例。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
ossClient = OSSClientBuilder.create()
.endpoint(aliyunOssProperties.getEndpoint())
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(aliyunOssProperties.getRegion())
.build();
// 生成按照时间日期划分的唯一文件名称
String objectName = generateObjectName(fileName);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(aliyunOssProperties.getBucketName(), objectName, inputStream);
// 创建PutObject请求。
ossClient.putObject(putObjectRequest);
return getFileUrl(objectName);
} catch (Exception oe) {
oe.printStackTrace();
throw new BusinessException("阿里云OSS文件上传出现异常");
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
// 生成按照时间日期划分的唯一文件名称
private static String generateObjectName(String fileName) {
// 对原始文件名称进行改写, 生成唯一文件名(UUID)
String uuid = UUID.randomUUID().toString().replace("-", "");
String suffix = fileName.substring(fileName.lastIndexOf('.'));
String objectName = uuid + suffix; // ae518b7f7e5742a19690c8ba53050fff.jpg
// 生成按照年月日格式化的时间目录
String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")); // 2026/09/26
// 重新拼接objectName
objectName = datePath + "/" + objectName;
return objectName;
}
/**
* 拼接文件的访问路径: https://{bucketName}.{endpoint主机}/{objectName}
*/
private String getFileUrl(String objectName) {
String host = aliyunOssProperties.getEndpoint().replaceFirst("^https?://", "");
return String.format("https://%s.%s/%s", aliyunOssProperties.getBucketName(), host, objectName);
}
}测试类编写
在qk-management的test目录下创建com.cghbh的目录,在这个目录下创建测试类,因为我们现在开始是通过application.yml配置来获取alioss的配置,所以需要在启动类所在的包中创建测试类。代码参考如下:
package com.cghbh;
import com.cghbh.util.OssTemplate;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
@SpringBootTest
public class OssTemplateTest {
@Autowired
private OssTemplate ossTemplate;
@Test
void testOss() throws FileNotFoundException {
String objectName = "zuoxishijian1.jpg";
// 填写本地文件的完整路径
String filePath = "C:\\Users\\gchen\\Desktop\\zuoxishijian.jpg";
InputStream inputStream = new FileInputStream(filePath);
// 前面是上传到阿里云oss桶里的名字
String url = ossTemplate.upload("wahaha.jpg", inputStream);
System.out.println(url);
}
}集成到项目中
接下来我们把阿里云oss集成到当前的项目中,主要流程如下:
- 用户点击头像上传图片到我们的程序,我们需要再Controller的方法中接收一个
MultipartFile类型的对象(这是SpringBoot提供的专门接收文件的对象) - 在方法中调用上一章节完成的工具类方法实现文件上传功能
- 将上传后的文件访问地址返回给前端
创建UploadController
注意:下面代码中获取文件上传的请求虽然是POST请求,但是我们拿到文件的方式依然是@RequestParam,因为框架底层帮我们进行了处理,我们按照这种规范要求开发即可。
package com.cghbh.controller;
import com.cghbh.common.Result;
import com.cghbh.util.OssTemplate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@RestController
@RequiredArgsConstructor
@Slf4j
public class UploadController {
private final OssTemplate ossTemplate;
@PostMapping("/upload")
public Result updateAvatar(@RequestParam("image") MultipartFile file) throws IOException {
String url = ossTemplate.upload("测试的名字.png", file.getInputStream());
return Result.success(url);
}
}在application.yml中增加配置
#数据库连接信息
spring:
servlet:
multipart:
max-file-size: 10MB # 单文件最大值,默认10MB
max-request-size: 100MB # 单个请求中文件总大小 , 默认100MB