SpringBoot 整合 阿里云OSS对象存储服务

今天来整合一下SpringBoot和阿里云OSS对象存储服务。


一、配置OSS服务

先在阿里云开通对象存储服务,拿到AccessKeyId、AccessKeySecret。
在这里插入图片描述
创建你的bucket(存储空间),相当于一个一个的文件夹目录。按业务需求分类存储你的文件,图片,音频,app包等等。创建bucket是要选择该bucket的权限,私有,公共读,公共读写,按需求选择。创建bucket时对应的endpoint要记住,上传文件需要用到。
在这里插入图片描述
可以配置bucket的生命周期,比如说某些文件有过期时间的,可以配置一下。
在这里插入图片描述


二、代码实现

引入依赖包

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

配置文件application.yml

aliyun-oss:
  #bucket名称
  bucketApp: xxx-app
  domainApp: https://xxx-app.oss-cn-shenzhen.aliyuncs.com/
  region: oss-cn-shenzhen
  endpoint : https://oss-cn-shenzhen.aliyuncs.com
  accessKeyId: 你的accessKeyId
  accessKeySecret: 你的accessKeySecret

对应上面配置文件的properties类

package com.example.file.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "aliyun-oss")
@Data
public class AliyunOSSProperties {

    /**
     * 服务器地点
     */
    private String region;
    /**
     * 服务器地址
     */
    private String endpoint;
    /**
     * OSS身份id
     */
    private String accessKeyId;
    /**
     * 身份密钥
     */
    private String accessKeySecret;

    /**
     * App文件bucketName
     */
    private String bucketApp;
    /**
     * App包文件地址前缀
     */
    private String domainApp;
}

上传文件工具类

package com.example.file.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.example.common.exception.BusinessErrorCode;
import com.example.common.exception.BusinessException;
import com.example.common.utils.FileIdUtils;
import com.example.file.config.AliyunOSSProperties;
import com.example.file.config.FileTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Component
public class AliyunOSSUtil {

    @Autowired
    private AliyunOSSProperties aliyunOSSProperties;

    private static Logger logger = LoggerFactory.getLogger(AliyunOSSUtil.class);

    /**
     * 文件不存在
     */
    private final String NO_SUCH_KEY = "NoSuchKey";
    /**
     * 存储空间不存在
     */
    private final String NO_SUCH_BUCKET = "NoSuchBucket";

    /**
     * 上传文件到阿里云 OSS 服务器
     *
     * @param files
     * @param fileTypeEnum
     * @param bucketName
     * @param storagePath
     * @return
     */
    public List<String> uploadFile(MultipartFile[] files, FileTypeEnum fileTypeEnum, String bucketName, String storagePath, String prefix) {
        //创建OSSClient实例
        OSSClient ossClient = new OSSClient(aliyunOSSProperties.getEndpoint(), aliyunOSSProperties.getAccessKeyId(), aliyunOSSProperties.getAccessKeySecret());
        List<String> fileIds = new ArrayList<>();
        try {
            for (MultipartFile file : files) {
           		//创建一个唯一的文件名,类似于id,就是保存在OSS服务器上文件的文件名(自定义文件名)
                String fileName = FileIdUtils.creater(fileTypeEnum.getCode());
                InputStream inputStream = file.getInputStream();
                ObjectMetadata objectMetadata = new ObjectMetadata();
                //设置数据流里有多少个字节可以读取
                objectMetadata.setContentLength(inputStream.available());
                objectMetadata.setCacheControl("no-cache");
                objectMetadata.setHeader("Pragma", "no-cache");
                objectMetadata.setContentType(file.getContentType());
                objectMetadata.setContentDisposition("inline;filename=" + fileName);
                fileName = StringUtils.isNotBlank(storagePath) ? storagePath + "/" + fileName : fileName;
                //上传文件
                PutObjectResult result = ossClient.putObject(bucketName, fileName, inputStream, objectMetadata);
                logger.info("Aliyun OSS AliyunOSSUtil.uploadFileToAliyunOSS,result:{}", result);
                fileIds.add(prefix + fileName);
            }
        } catch (IOException e) {
            logger.error("Aliyun OSS AliyunOSSUtil.uploadFileToAliyunOSS fail,reason:{}", e);
        } finally {
            ossClient.shutdown();
        }
        return fileIds;
    }

    /**
     * 删除文件
     *
     * @param fileName
     * @param bucketName
     */
    public void deleteFile(String fileName, String bucketName) {
        OSSClient ossClient = new OSSClient(aliyunOSSProperties.getEndpoint(), aliyunOSSProperties.getAccessKeyId(), aliyunOSSProperties.getAccessKeySecret());
        ossClient.deleteObject(bucketName, fileName);
        shutdown(ossClient);
    }

    /**
     * 根据图片全路径删除就图片
     *
     * @param imgUrl     图片全路径
     * @param bucketName 存储路径
     */
    public void delImg(String imgUrl, String bucketName) {
        if (StringUtils.isBlank(imgUrl)) {
            return;
        }
        //问号
        int index = imgUrl.indexOf('?');
        if (index != -1) {
            imgUrl = imgUrl.substring(0, index);
        }
        int slashIndex = imgUrl.lastIndexOf('/');
        String fileId = imgUrl.substring(slashIndex + 1);
        OSSClient ossClient = new OSSClient(aliyunOSSProperties.getEndpoint(), aliyunOSSProperties.getAccessKeyId(), aliyunOSSProperties.getAccessKeySecret());
        ossClient.deleteObject(bucketName, fileId);
        shutdown(ossClient);
    }

    /**
     * 判断文件是否存在
     *
     * @param fileName   文件名称
     * @param bucketName 文件储存空间名称
     * @return true:存在,false:不存在
     */
    public boolean doesObjectExist(String fileName, String bucketName) {
        Validate.notEmpty(fileName, "fileName can be not empty");
        Validate.notEmpty(bucketName, "bucketName can be not empty");
        OSSClient ossClient = new OSSClient(aliyunOSSProperties.getEndpoint(), aliyunOSSProperties.getAccessKeyId(), aliyunOSSProperties.getAccessKeySecret());
        try {
            boolean found = ossClient.doesObjectExist(bucketName, fileName);
            return found;
        } finally {
            shutdown(ossClient);
        }

    }

    /**
     * 复制文件
     *
     * @param fileName              源文件名称
     * @param bucketName            源储存空间名称
     * @param destinationBucketName 目标储存空间名称
     * @param destinationObjectName 目标文件名称
     */
    public void ossCopyObject(String fileName, String bucketName, String destinationBucketName, String destinationObjectName) {
        Validate.notEmpty(fileName, "fileName can be not empty");
        Validate.notEmpty(bucketName, "bucketName can be not empty");
        Validate.notEmpty(destinationBucketName, "destinationBucketName can be not empty");
        Validate.notEmpty(destinationObjectName, "destinationObjectName can be not empty");
        OSSClient ossClient = new OSSClient(aliyunOSSProperties.getEndpoint(), aliyunOSSProperties.getAccessKeyId(), aliyunOSSProperties.getAccessKeySecret());
        // 拷贝文件。
        try {
            ossClient.copyObject(bucketName, fileName, destinationBucketName, destinationObjectName);
        } catch (OSSException oe) {
            logger.error("errorCode:{},Message:{},requestID:{}", oe.getErrorCode(), oe.getMessage(), oe.getRequestId());
            if (oe.getErrorCode().equals(NO_SUCH_KEY)) {
                throw new BusinessException(BusinessErrorCode.NO_SUCH_KEY);
            } else if (oe.getErrorCode().equals(NO_SUCH_BUCKET)) {
                throw new BusinessException(BusinessErrorCode.NO_SUCH_BUCKET);
            } else {
                throw new BusinessException(BusinessErrorCode.FAIL);
            }
        } finally {
            shutdown(ossClient);
        }
    }

    /**
     * 关闭oos
     *
     * @param ossClient ossClient
     */
    private void shutdown(OSSClient ossClient) {
        ossClient.shutdown();
    }
}

文件类型枚举

package com.example.file.config;

public enum FileTypeEnum {

    IMG(1, "图片"),
    AUDIO(2, "音频"),
    VIDEO(3, "视频"),
    APP(4, "App包"),
    OTHER(5, "其他");

    private Integer code;
    private String message;

    FileTypeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

}

调用工具类上传文件

@Override
    public List<String> uploadImg(MultipartFile[] files) {
        if (files == null) {
            throw new BusinessException(BusinessErrorCode.OPT_UPLOAD_FILE);
        }
        try {
            return aliyunOSSUtil.uploadFile(files, FileTypeEnum.IMG, aliyunOSSProperties.getBucketProduct(), null, aliyunOSSProperties.getDomainProduct());
        } catch (Exception e) {
            logger.error("uploadImg error e:{}", e);
            throw new BusinessException(BusinessErrorCode.UPLOAD_FAIL);
        }
    }

返回的List是文件上传之后文件的文件名集合。
到此就整合完成了。可以登录OSS控制台查看对应的文件。


  • 我的公众号:Coding抠腚
  • 一个没有福报的社畜程序员。吐槽程序员生存,生活,职业发展。Java学习路线,经验,技术分享。技术问题交流探讨。超喜欢这里的,这里的老哥写代码都好sao的。
    Coding抠腚

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值