Skip to content

引入依赖 ​

在qk-common模块的pom.xml引入下面的依赖,其中版本锁定需要在父模块中完成,此处不再赘述。

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要换成自己申请的密钥

Bash
setx OSS_ACCESS_KEY_ID "YOUR_ACCESS_KEY_ID"
setx OSS_ACCESS_KEY_SECRET "YOUR_ACCESS_KEY_SECRET"

运行以下命令,检查环境变量是否生效。

Bash
echo %OSS_ACCESS_KEY_ID%
echo %OSS_ACCESS_KEY_SECRET%

也可以在系统的环境变量中配置,需要重启下系统。

编写测试代码 ​

在qk-common的test目录下新建com.cghbh包,创建下面的配置文件,直接在com.cghbh目录下粘贴可以快速创建整个文件。

java
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注解读取配置文件信息,需要额外添加一个依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
</dependency>

修改application.yml配置文件, 添加阿里云OSS相关配置。

自定义配置如何读取

SpringBoot项目中读取自定义信息的方式有两种

  1. 在属性上使用 @Value("${``aliyun.oss.endpoint``}")注解的方式一个个读取配置
  2. 使用@ConfigurationProperties(``prefix='配置前缀'``) 注解批量读取自定义配置

使用方案1获取配置的代码如下(在qk-common包中创建OssTemplate文件):

java
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文件):

java
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配置如下:

yml
# 阿里云oss配置
aliyun:
  oss:
    endpoint: https://oss-cn-shanghai.aliyuncs.com
    bucketName: heima-qkxxx
    region: cn-shanghai

功能封装 ​

为了方便后续程序的扩展和维护,我们需要对阿里云oss进行工具的封装。在qk-common模块中创建com.cghbh.util包,然后创建OssTemplate 类(修改测试程序,封装成工具类如下):

java
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的配置,所以需要在启动类所在的包中创建测试类。代码参考如下:

java
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集成到当前的项目中,主要流程如下:

  1. 用户点击头像上传图片到我们的程序,我们需要再Controller的方法中接收一个MultipartFile类型的对象(这是SpringBoot提供的专门接收文件的对象)
  2. 在方法中调用上一章节完成的工具类方法实现文件上传功能
  3. 将上传后的文件访问地址返回给前端

创建UploadController ​

注意:下面代码中获取文件上传的请求虽然是POST请求,但是我们拿到文件的方式依然是@RequestParam,因为框架底层帮我们进行了处理,我们按照这种规范要求开发即可。

java
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中增加配置 ​

yml
#数据库连接信息
spring:
  servlet:
    multipart:
      max-file-size: 10MB  # 单文件最大值,默认10MB
      max-request-size: 100MB  # 单个请求中文件总大小 , 默认100MB