首页 > 其他分享 >【服务集成】最新版 | 阿里云OSS对象存储服务使用教程(包含OSS工具类优化、自定义阿里云OSS服务starter)

【服务集成】最新版 | 阿里云OSS对象存储服务使用教程(包含OSS工具类优化、自定义阿里云OSS服务starter)

时间:2024-09-21 17:23:20浏览次数:3  
标签:文件 服务 uploadDir OSS 阿里 aliyun 上传 oss

文章目录


一、阿里云OSS对象存储服务介绍

阿里云对象存储OSS(Object Storage Service),是一款海量、安全、低成本、高可靠的云存储服务。使用OSS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

相当于一个云储存服务器,可以把我们的文件存储到阿里云的服务器中。在我们使用了阿里云OSS对象存储服务之后,我们的项目当中如果涉及到文件上传这样的业务,在前端进行文件上传并请求到服务端时,在服务器本地磁盘当中就不需要再来存储文件了。我们直接将接收到的文件上传到oss,由oss帮我们存储和管理,同时阿里云的oss存储服务还保障了我们所存储内容的安全可靠。

第三方服务使用的通用思路,我们做一个简单介绍之后,接下来我们就来介绍一下我们当前要使用的阿里云oss对象存储服务具体的使用步骤。

Bucket:存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间。

SDK:Software Development Kit 的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK。

简单说,sdk中包含了我们使用第三方云服务时所需要的依赖,以及一些示例代码。我们可以参照sdk所提供的示例代码就可以完成入门程序。


二、服务开通与使用准备

1、准备工作

注册阿里云账户(注册完成后需要实名认证),注册完账号之后登录阿里云

产品搜索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配置访问凭证为例(其他系统请参考官方文档)

管理员身份打开CMD命令行,执行如下命令,配置系统的环境变量。

set OSS_ACCESS_KEY_ID=yourAccessKeyId
set OSS_ACCESS_KEY_SECRET=yourAccessKeySecret

注意:将上述的ACCESS_KEY_ID 与 ACCESS_KEY_SECRET 的值要替换成自己的。

执行如下命令,让更改生效。

setx OSS_ACCESS_KEY_ID "%OSS_ACCESS_KEY_ID%"
setx OSS_ACCESS_KEY_SECRET "%OSS_ACCESS_KEY_SECRET%"

执行如下命令,验证环境变量是否生效。

echo %OSS_ACCESS_KEY_ID%
echo %OSS_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";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_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 += "/";
        
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_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

对于不熟悉SpringBoot自动装配原理自定义starter 的朋友,一定要先看这两篇:
[1] 最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
[2] 最新版 | SpringBoot3如何自定义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文件:

  • 引入阿里云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>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- 阿里云OSS的自动配置类 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <!-- 配置插件解决java:错误:不支持发行版本5 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</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>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </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>

    <!-- 配置插件解决java:错误:不支持发行版本5 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</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("."));

        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_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;	// 注意这里和之前不同,导入的是我们自定义的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文件上传成功!



标签:文件,服务,uploadDir,OSS,阿里,aliyun,上传,oss
From: https://blog.csdn.net/weixin_52152676/article/details/142332699

相关文章

  • ​​Prometheus监控之服务发现
    1.Prometheus服务发现1.1为什么需要服务发现Prometheus采⽤Pull模型来抓取⽬标主机的指标数据,这就意味着Prometheus必须事先知道每个要监控的⽬标的端点地址。然后才能从对应的Exporter或Instrumentation进⾏数据抓取。对于规模较⼩,且监控的⽬标不会频繁的发⽣变动,直接使⽤但......
  • 1.JDK自带的线程池有哪些?2.线程池中核心线程数与最大线程数与缓冲任务队列的关系?3.为
    1.JDK自带的线程池有哪些?2.线程池中核心线程数与最大线程数与缓冲任务队列的关系?在Java中的线程池(如ThreadPoolExecutor)中,核心线程数(corePoolSize)、最大线程数(maximumPoolSize)以及缓冲队列(workQueue)之间存在着密切的关系,它们共同决定了线程池如何管理和调度任务。以下是......
  • 服务API接口:解锁API接口参数的奥秘
    在软件开发中,API接口参数是构建有效通信的核心。它们定义了API调用的方式和数据交换的规则,对于确保API的功能性和可用性至关重要。本文将深入探讨服务API接口中的参数,揭示如何通过精心设计的参数提升API的性能和用户体验。什么是API接口参数?API接口参数是在调用API时传递给API的数......
  • 使用 Nginx 搭建 Webdav 服务
    使用Nginx搭建Webdav服务一、自签名根证书1.生成根证书密钥opensslgenrsa-out./root.key20482.生成根证书opensslreq-x509-new-key./root.key-out./root.pem-days365交互信息CountryName(2lettercode)[]:CNStateorProvinceName(fullname)......
  • springboot交通管理在线服务系统的开发
    文章目录目录文章目录论文目录项目介绍开发环境系统实现论文参考论文目录第1章 绪论1.1选题动因1.2目的和意义1.3论文结构安排第2章 开发环境与技术2.1MYSQL数据库2.2 Tomcat介绍2.3 vue技术2.4 SpringBoot框架第3章 系统分析3.1可行性......
  • 数据库连接错误:您在wp-config.php文件中提供的数据库用户名和密码可能不正确,或者无法
    为了解决“数据库连接错误”的问题,可以按照以下步骤进行操作:备份现有配置:在修改任何文件之前,请确保备份现有的wp-config.php文件,以防修改出错时能够恢复。重命名配置文件:将根目录下的wp-config-sample.php文件重命名为wp-config.php。这通常可以通过FTP客户端或通过服务器上......
  • 如何查看linux上对应的dhcp服务器IP是多少
    如何查看linux上对应的dhcp服务器IP是多少要查看Linux系统上对应的DHCP服务器IP地址,可以通过以下几种方法:1.检查DHCP客户端日志在DHCP客户端获取IP地址的过程中,DHCP服务器的IP地址通常会记录在系统日志中。可以使用grep命令查找包含"DHCPOFFER"的日志条......
  • 基于大数据技术的智慧居家养老服务平台
    项目介绍大数据分析是现下比较热门的词汇,通过分析之后可以得到更多深入且有价值的信息。现实的科技手段中,越来越多的应用都会涉及到大数据随着大数据时代的到来,数据挖掘、分析与应用成为多个行业的关键,本课题首先介绍了网络爬虫的基本概念以及技术实现方法,重点关注爬虫的......
  • 在 Ubuntu 20.04 服务器上安装 Python 3 并设置编程环境的方法
    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。简介Python编程语言越来越受到初学者和经验丰富的开发人员的青睐。Python灵活多变,在脚本编写、自动化、数据分析、机器学习和后端开发等方面具有优势。Python首次发布于......
  • 帝国cms数据库在哪_CMS发布服务配置说明
    1.数据库配置文件路径帝国7.0之前的版本:路径:e/class/config.php该文件包含数据库连接的所有必要设置,如服务器地址、用户名、密码等。帝国7.0及以后的版本:路径:e/config/config.php更改路径的目的在于简化文件结构,便于后续升级和维护。2.重要性与功能配置正确性:......