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

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 阿里云OSS(Object Storage Service)是一种安全、可靠且成本低廉的云存储服务,支持海量数据存储。用户可通过网络轻松存储和访问各类文件,如文本、图片、音频和视频等。使用OSS后,项目中的文件上传业务无需在服务器本地磁盘存储文件,而是直接上传至OSS,由其管理和保障数据安全。此外,介绍了OSS服务的开通流程、Bucket创建、AccessKey配置及环境变量设置,并提供了Java SDK示例代码,帮助用户快速上手。最后,展示了如何通过自定义starter简化工具类集成,实现便捷的文件上传功能。

一、阿里云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配置访问凭证为例(其他系统请参考官方文档)
管理员身份 打开CMD命令行,执行如下命令,配置系统的环境变量。
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文件上传成功!


相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
相关文章
|
1月前
|
存储 数据可视化 Java
基于MicrometerTracing门面和Zipkin实现集成springcloud2023的服务追踪
Sleuth将会停止维护,Sleuth最新版本也只支持springboot2。作为替代可以使用MicrometerTracing在微服务中作为服务追踪的工具。
106 1
|
2月前
|
Java Maven Windows
使用Java创建集成JACOB的HTTP服务
本文介绍了如何在Java中创建一个集成JACOB的HTTP服务,使Java应用能够调用Windows的COM组件。文章详细讲解了环境配置、动态加载JACOB DLL、创建HTTP服务器、实现IP白名单及处理HTTP请求的具体步骤,帮助读者实现Java应用与Windows系统的交互。作者拥有23年编程经验,文章来源于稀土掘金。著作权归作者所有,商业转载需授权。
使用Java创建集成JACOB的HTTP服务
|
19天前
|
安全 Java API
【三方服务集成】最新版 | 阿里云短信服务SMS使用教程(包含支持单双参数模板的工具类,拿来即用!)
阿里云短信服务提供API/SDK和控制台调用方式,支持验证码、通知、推广等短信类型。需先注册阿里云账号并实名认证,然后在短信服务控制台申请资质、签名和模板,并创建AccessKey。最后通过Maven引入依赖,使用工具类发送短信验证码。
【三方服务集成】最新版 | 阿里云短信服务SMS使用教程(包含支持单双参数模板的工具类,拿来即用!)
|
23天前
|
安全 测试技术 数据安全/隐私保护
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
|
1月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
96 9
|
1月前
|
安全 Java 测试技术
ToB项目身份认证AD集成(二):快速搞定window server 2003部署AD域服务并支持ssl
本文详细介绍了如何搭建本地AD域控测试环境,包括安装AD域服务、测试LDAP接口及配置LDAPS的过程。通过运行自签名证书生成脚本和手动部署证书,实现安全的SSL连接,适用于ToB项目的身份认证集成。文中还提供了相关系列文章链接,便于读者深入了解AD和LDAP的基础知识。
|
2月前
|
编解码 Linux 开发工具
Linux平台x86_64|aarch64架构RTMP推送|轻量级RTSP服务模块集成说明
支持x64_64架构、aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需要GLib–2.0, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9)。
|
3月前
|
域名解析 网络协议 API
【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
|
3月前
|
机器人 C# 人工智能
智能升级:WPF与人工智能的跨界合作——手把手教你集成聊天机器人,打造互动新体验与个性化服务
【8月更文挑战第31天】聊天机器人已成为现代应用的重要组成部分,提供即时响应、个性化服务及全天候支持。随着AI技术的发展,聊天机器人的功能日益强大,不仅能进行简单问答,还能实现复杂对话管理和情感分析。本文通过具体案例分析,展示了如何在WPF应用中集成聊天机器人,并通过示例代码详细说明其实现过程。使用Microsoft的Bot Framework可以轻松创建并配置聊天机器人,增强应用互动性和用户体验。首先,需在Bot Framework门户中创建机器人项目并编写逻辑。然后,在WPF应用中添加聊天界面,实现与机器人的交互。
104 0
|
3月前
|
SQL 网络协议 安全
【Azure API 管理】APIM集成内网虚拟网络后,启用自定义路由管理外出流量经过防火墙(Firewall),遇见APIs加载不出来问题
【Azure API 管理】APIM集成内网虚拟网络后,启用自定义路由管理外出流量经过防火墙(Firewall),遇见APIs加载不出来问题

相关产品

  • 对象存储
  • 下一篇
    无影云桌面