目录

  • 前言
  • 一、阿里云oss简介
  • 二、使用步骤
  • 1.引入依赖
  • 3.完整依赖
  • 4.yml配置文件
  • 5.配置类代码
  • 6.工具类代码
  • 7.控制类
  • 8.postmen请求调用
  • 总结:
  • 拓展:



前言

技术不断革新,优胜略汰,不断努力成长是为长远计。


一、阿里云oss简介

阿里云的oss对象存储是新型的云存储工具,详细介绍请参考oss介绍注:oss相关名词如endpoint、accessKeyId、bucketName等后面扩展中会作简略描述,详细了解可自行百度也可去官网查看API。

二、使用步骤

开发环境:

JDK版本:1.8
maven版本:3.9.0
开发工具:IDEA社区版ideaIC-2018.3
项目框架:spring boot 版本为 2.6.3 springboot搭建传送门

1.引入依赖

pom中添加阿里云oss的依赖

<!-- aliyun-oss -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.16.0</version>
        </dependency>

3.完整依赖

完整pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>oss_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>

        <!--SpringBoot启动依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.6.3</version>
            <scope>test</scope>
        </dependency>

        <!-- aliyun-oss -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.16.0</version>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>

        <!-- fastjson -->
<!--        <dependency>-->
<!--            <groupId>com.alibaba</groupId>-->
<!--            <artifactId>fastjson</artifactId>-->
<!--            <version>2.0.23</version>-->
<!--        </dependency>-->
        
    </dependencies>
    
</project>

注:不知道哪里用到了lombok注解,但不用lombok注解就会报下面这个错,所以还是添上了

[ErrorCode]: SocketException
[RequestId]: Unknown

4.yml配置文件

application.yml

server:
  port: 8088

aliyun:
  oss:
    endpoint: oss-cn-shanghai.aliyuncs.com
    accessKeyId: uU2e3lsseG9KDEDGDERDFSFADSDFDExdsdse
    accessKeySecret: DJFLDasdljEDldld8lDE34ldrd8

注:这里配置的endpoint/accessKeyId/accessKeySecret参数均为随机输入,无效,请根据自己的oss替换掉对应参数(如何在oss中查看这几个参数请参考阿里云官网文档)。

5.配置类代码

OssConfig.java

package com.oss.config;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassDescription: 通过value注解将参数从yml配置文件中读取过来,创建为bean在方法中调用
 * @Author:李白
 * @Date:2023/3/6 16:13
 */
@Configuration
public class OssConfig {
    @Value("${aliyun.oss.endpoint}")
    public String endpoint;

    @Value("${aliyun.oss.accessKeyId}")
    public String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    public String accessKeySecret;

    @Bean
    public OSS oss(){
        return new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);
    }
}

6.工具类代码

包含了多种存取数据方法
OssUtil.java

package com.oss.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.*;

/**
 * @ClassDescription: 操作oss数据存取等的工具类
 * @Author:李白
 * @Date:2023/3/6 16:18
 */
@Component
public class OssUtil {
    
    /**
     * 此处的oss是将配置文件中的参数配置后生成bean,通过自动注入来获取配置参数后的对象oss
     */
    @Autowired
    private OSS oss;
    /**
     * 为了能在每个方法中使用配置号参数的oss对象,需要将其静态化,如果oss被static修饰,则每次调用时oss都是空,所以这里需要做一下转换
     * 通过postConstruct注解将oss转为静态的ossP,这样在每次调用时都是配置好的参数的一个oss对象
     * @PostConstruct是Java自带的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。
     * @postConstruct可以修饰一个非静态的void方法,使用场景为:在生成对象时想完成某些初始化操作,初始化又依赖于自动注入,构造方法中无法实现时
     * 使用此注解修饰一个方法来实现初始化操作,注解的方法会在自动注入完成后被调用-----执行顺序--》construct构造函数-》@Autowired自动注入-》@PostConstruct
     */
    private static OSS ossP;

    /**
     * 默认的oss桶位置
     */
    public static final String fixedBucket = "bucketName-123";

    @PostConstruct
    public void ossTransfer(){
        //该方法会在上面的依赖注入后自动被调用
        ossP = oss;
    }


    /**
     * 上传字符串
     * @param objectName oss文件全路径名-默认是桶位置加全路径名,如桶位置为ossbucket,全路径名为upload/string/str.json,则数据会放到ossbucket下的upload/string包中,文件名为str.json
     * @param content 上传内容
     */
    public static void uploadString(String objectName, String content){
        PutObjectRequest putObjectRequest = new PutObjectRequest(fixedBucket, objectName, new ByteArrayInputStream(content.getBytes()));
        ossP.putObject(putObjectRequest);
    }

    /**
     * 上传字符串
     * @param bucketName 文件存在oss的桶名称
     * @param objectName 文件在oss中的全路径
     * @param content 上传内容
     */
    public static void uploadString(String bucketName, String objectName, String content){
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
        ossP.putObject(putObjectRequest);
    }

    /**
     * 上传文件
     * @param objectName 文件在oss中的全路径
     * @param filePath 上传文件的本地路径
     */
    public static void uploadFile(String objectName, String filePath){
        PutObjectRequest putObjectRequest = new PutObjectRequest(fixedBucket, objectName, new File(filePath));
        ossP.putObject(putObjectRequest);
    }

    /**
     * 上传文件
     * @param bucketName 文件所在oss桶名称
     * @param objectName 文件在oss中的全路径
     * @param filePath 上传文件的本地路径
     */
    public static void uploadFile(String bucketName, String objectName, String filePath){
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
        ossP.putObject(putObjectRequest);
    }

    /**
     * 上传multi文件
     * @param objectName 文件全路径
     * @param multipartFile 上传的文件
     */
    public static void uploadMultipartFile(String objectName, MultipartFile multipartFile){
        byte[] bytes = new byte[0];
        try {
            bytes = multipartFile.getBytes();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        InputStream inputStream = new ByteArrayInputStream(bytes);
        PutObjectRequest putObjectRequest = new PutObjectRequest(fixedBucket, objectName, inputStream);
        ossP.putObject(putObjectRequest);
    }

    /**
     * multi方式上传文件
     * @param bucketName oss中桶名称
     * @param objectName 文件在oss中的全路径
     * @param multipartFile 上传的文件
     */
    public static void uploadMultipartFile(String bucketName, String objectName, MultipartFile multipartFile){
        byte[] bytes = new byte[0];
        try {
            bytes = multipartFile.getBytes();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        InputStream inputStream = new ByteArrayInputStream(bytes);
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
        ossP.putObject(putObjectRequest);
    }

    /**
     * 上传流数据
     * @param objectName 数据在oss中的全路径
     * @param inputStream 流数据内容
     */
    public static void uploadStream(String objectName, InputStream inputStream){
        PutObjectRequest putObjectRequest = new PutObjectRequest(fixedBucket, objectName, inputStream);
        ossP.putObject(putObjectRequest);
    }

    /**
     * 上传流数据
     * @param bucketName oss桶名称
     * @param objectName 数据所在oss中的全路径
     * @param inputStream 流数据
     */
    public static void uploadStream(String bucketName, String objectName, InputStream inputStream){
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
        ossP.putObject(putObjectRequest);
    }

    /**
     * 下载字符串数据
     * @param objectName 数据所在oss的全路径
     * @return 字符串
     * @throws IOException
     */
    public static String downloadString(String objectName) throws IOException {
        OSSObject ossObject = ossP.getObject(fixedBucket, objectName);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        StringBuilder stringBuilder = new StringBuilder();
        while (true){
            String line = bufferedReader.readLine();
            if(line==null){
                break;
            }else {
                stringBuilder.append(line);
            }
        }
        bufferedReader.close();
        return stringBuilder.toString();
    }

    /**
     * 下载字符串数据
     * @param bucketName oss桶位置
     * @param objectName 数据所在oss中的全路径
     * @return 返回字符串
     * @throws IOException
     */
    public static String downloadString(String bucketName, String objectName) throws IOException {
        OSSObject ossObject = ossP.getObject(bucketName, objectName);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        StringBuilder stringBuilder = new StringBuilder();
        while (true){
            String line = bufferedReader.readLine();
            if(line==null){
                break;
            }else {
                stringBuilder.append(line);
            }
        }
        bufferedReader.close();
        return stringBuilder.toString();
    }

    /**
     * 下载文件
     * @param objectName 数据所在oss全路径
     * @param fileName 文件名
     */
    public static void downloadFile(String objectName, String fileName){
        ossP.getObject(new GetObjectRequest(fixedBucket, objectName),new File(fileName));
    }

    /**
     * 下载文件
     * @param bucketName 文件所在oss桶名称
     * @param objectName  文件所在oss中的全路径
     * @param fileName 文件名
     */
    public static void downloadFile(String bucketName, String objectName, String fileName){
        ossP.getObject(new GetObjectRequest(bucketName, objectName),new File(fileName));
    }

    /**
     * 删除数据
     * @param objectName 删除文件的全路径
     */
    public static void delete(String objectName){
        ossP.deleteObject(fixedBucket, objectName);
    }

    /**
     * 删除数据
     * @param bucketName 桶名称
     * @param objectName 删除文件的全路径
     */
    public static void delete(String bucketName, String objectName){
        ossP.deleteObject(bucketName, objectName);
    }

    /**
     * 检查文件是否存在
     * @param objectName 文件所在oss中的全路径
     * @return 返回是否
     */
    public static boolean checkExist(String objectName){
        boolean exist = ossP.doesObjectExist(fixedBucket, objectName);
        return exist;
    }

    /**
     * 检查文件是否存在
     * @param bucketName 桶名称
     * @param objectName 文件所在oss中的全路径
     * @return 返回是否
     */
    public static boolean checkExist(String bucketName, String objectName){
        boolean exist = ossP.doesObjectExist(bucketName, objectName);
        return exist;
    }

    //如果需要使用异步调用则在需要的方法上加上@Async注解即可
    

}

7.控制类

这里只以存取字符串为例展示存取功能
OssController.java

package com.oss.controller;

import com.oss.utils.OssUtil;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;

/**
 * @ClassDescription: 控制类,操作数据存取的请求接口
 * @Author:李白
 * @Date:2023/3/7 11:38
 */
@RestController
@EnableAutoConfiguration
@RequestMapping("/oss-test")
public class OssController {

    @CrossOrigin
    @RequestMapping(value = "/up",method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String ossUpload(){

        String bucketName = "bucketName-123";
        String upStringContent = "this is a oss test content";
        String fileName = "test2.text";
        String objectName = "321folder/21oss/"+fileName;
        OssUtil.uploadString(bucketName, objectName, upStringContent);

        return "oss 上传数据!";

    }

    @CrossOrigin
    @RequestMapping(value = "/down",method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public String ossDownload() throws IOException {

        String bucketName = "bucketName-123";
        String fileName = "test2.text";
        String objectName = "321folder/21oss/"+fileName;
        String fileContent = OssUtil.downloadString(bucketName, objectName);

        return "oss 下载数据 内容:"+fileContent;
    }
}

8.postmen请求调用

上传数据:

127.0.0.1:8088/oss-test/up

oss客户端查看:

springBoot的项目中可以存储md我呢见吗 springboot 对象存储_spring boot

下载(读取)数据:

127.0.0.1:8088/oss-test/down

postman返回读取内容:

springBoot的项目中可以存储md我呢见吗 springboot 对象存储_spring boot_02


总结:

1这里只以字符串为例实现了存取,工具类中包含文件、流、字符串等方式进行存取数据,基本都是一样的操作。
2对于oss的使用,配置参数需要考虑到安全问题,所以最好是以读取参数的方式。其次在操作存取数据时,大一些的数据上传下载效率会变低,这时可以考虑用异步调用注解。
3需要注意的点是配置bean的时候参数字段不能用private修饰,虽然不会报错,但读取的时候是读不到私有参数生成的bean中的值的。


拓展:

对于oss相关的名词作一些了解:1.OSS-全称为Object Storage Service 对象存储服务,是一种使用HTTP API存储和检索非结构化数据和元数据对象的工具。 即将文件传到云数据库中,云数据库提供文件上传和下载等服务。
2.endipoint oss对外服务的访问域名,这里注意,内外网访问同一云数据库的域名是不同的。
3.accessKeyId 访问身份验证的用户标识。
4.accessKeySecret 用来身份验证的密钥(用户加密签名字符串、oss验证签名字符串的密钥,此密钥安全保存不要泄露)
5.bucket 存储空间,用于存储对象的容器,数据隶属于某个bucket。
6.bucketName 即bucket名,存储空间名称,又称为桶名称,是oss下最高一层的存储空间。
7.objcet 对象或者文件,是oss存储数据的基本单元,唯一标识为文件名(key)。
8.objectName 即objcet名,文件存储的路径(包含了文件名及后缀)。
9.region 地域,oss云数据库所在的地理位置,可根据自身情况选择数据存储的地域。