springboot整合阿里云oss实现文件上传

前言

项目中涉及到图片的都会使用阿里云oss文件上传,为了便于开发,特编写此文档。

前提条件

已经获取到阿里云oss的accessid和accesskey,且已经创建阿里云oss的bucket。其中,bucket的权限为公共读,这样可以通过bucket和endpoint的拼接查询图片路径。

1、在pom中添加相关依赖

<!--阿里云-->
<dependency>
  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-sdk-oss</artifactId>
  <version>3.15.1</version>
</dependency>

<!--整合Knife4j-->
<dependency>
  <groupId>com.github.xiaoymin</groupId>
  <artifactId>knife4j-spring-boot-starter</artifactId>
  <version>3.0.3</version>
</dependency>

<!--swagger2-->
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>${springfox-swagger2.version}</version>
</dependency>
<!--swagger-ui-->
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
  <version>${springfox-swagger-ui.version}</version>
</dependency>

<!--lombok-->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>

2、添加配置文件

ali:
  oss:
    accessId: xxx
    accessKey: xxxx
    bucket: testaaaa
    endpoint: # Endpoint:在阿里云oss控制台查看自己使用的endpoint,eg: oss-cn-shanghai.aliyuncs.com 
    tempFile: D:/temp/
    showUri: https://bucket名.enpoint/ #在系统中没有用到,只是一个记录作用,使用这个地址拼接上传的文件key查询图片

3、添加OSS的相关Java配置

用于配置OSS的连接客户端的OSSClient

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "ali.oss")
public class AliyunConfig {
    private String accessId;
    private String accessKey;
    private String bucket;
    private String endpoint;
    private String tempFile;
    private String showUri;
}

4、阿里云 oss 上传工具类

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.apache.poi.ss.usermodel.PictureData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 阿里云 oss 上传工具类
 */
@Component
@Slf4j
public class AliOssUtil {

    private AliOssUtil(){}

    static String endpoint = "";
    static String accessKeyId = "";
    static String accessKeySecret = "";
    static String bucketName = "";
    static String tempFile = "C:/temp/";



    /**
     * 上传图片到 Oss
     * @param key
     * @param multipartFile
     */
    public static String upload(String key, MultipartFile multipartFile){
        String suffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
        suffix = StringUtils.isNotBlank(suffix) ? suffix : "jpg";
        String filePath = String.join("", tempFile, key,".",suffix);
        key = String.join("",key,".",suffix);
        File file = null;
        try {
            FileUtil.mkdir(new File(tempFile));
            file = FileUtil.writeFromStream(multipartFile.getInputStream(), filePath);
            if(!file.exists()){
                throw new RuntimeException("上传的文件,保存到本地失败!");
            }
            log.info("[文件上传] 文件上传到本地成功,路径:{}",filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info("[文件上传] 准备上传文件到Oss..");
        //图片压缩
        String filePathCopy=String.join("", tempFile, key,"_copy.",suffix);
        File fileCopy = new File(filePathCopy);
        try {

            OutputStream out =new FileOutputStream(fileCopy);
            BufferedImage bufferedImage = ImageIO.read(new FileInputStream(file));
            Image image =bufferedImage.getScaledInstance(bufferedImage.getWidth(),bufferedImage.getHeight(),Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics graphics = tag.getGraphics();
            graphics.drawImage(image, 0,0,null);
            graphics.dispose();
            ImageIO.write(tag,"jpg",out);
        } catch (IOException e) {
            throw new RuntimeException("请输入jpg格式的图片");
        }
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        String path = String.join("", DateUtil.format(LocalDateTime.now(),"yyyy/MM/dd"),"/",key);
        PutObjectResult putObjectResult = ossClient.putObject(bucketName, path, new File(filePathCopy));
        log.info("[文件上传] 文件上传到Oss结果:{}", JSONObject.toJSONString(putObjectResult));
        log.info("[文件上传] 删除本地图片:{}",FileUtil.del(file));
        return path;
    }

    public static void upload(String key, File file){
        log.info("[文件上传] 准备上传文件到Oss..");
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        String path = String.join("", DateUtil.format(LocalDateTime.now(),"yyyy/MM/dd"),"/",key);
        PutObjectResult putObjectResult = ossClient.putObject(bucketName, path, file);
        log.info("[文件上传] 文件上传到Oss结果:{}", JSONObject.toJSONString(putObjectResult));
//        log.info("[文件上传] 删除本地图片:{}",FileUtil.del(file));
    }

    public static void main(String[] args) throws IOException {
        String s = UUID.randomUUID().toString();
        System.out.println(s);
        File file = new File("C:\\Users\\iFound\\Desktop\\bb.png");
        FileInputStream fileInputStream = new FileInputStream(file);
        MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getName(),
                ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);

        upload(s,multipartFile);
        //upload(s,new File("C:\\Users\\m\\Desktop\\微信截图_20220916171520.png"));
    }

    /**
     * 前端oss直传返回存储桶对象
     */
    public static OssConfigVO ossUpload(String picture){
        OssConfigVO ossConfigVO = new OssConfigVO();
        ossConfigVO.setEndpoint(endpoint);
        ossConfigVO.setAccessKeyId(accessKeyId);
        ossConfigVO.setAccessKeySecret(accessKeySecret);
        ossConfigVO.setBucketName(bucketName);
        ossConfigVO.setTempFile(tempFile);
        ossConfigVO.setPicture(picture);
        System.out.println();
        System.out.println(ossConfigVO);
        System.out.println();
        return ossConfigVO;
    }

    @Data
    public static class OssConfigVO {
        private String endpoint;
        private String accessKeyId;
        private String accessKeySecret;
        private String bucketName;
        private String tempFile;
        private String picture;
    }


    @Value("${ali.oss.endpoint}")
    public void setEndpoint(String endpoint) {
        AliOssUtil.endpoint = endpoint;
    }

    @Value("${ali.oss.accessId}")
    public void setAccessKeyId(String accessKeyId) {
        AliOssUtil.accessKeyId = accessKeyId;
    }

    @Value("${ali.oss.accessKey}")
    public void setAccessKeySecret(String accessKeySecret) {
        AliOssUtil.accessKeySecret = accessKeySecret;
    }

    @Value("${ali.oss.bucket}")
    public void setBucketName(String bucketName) {
        AliOssUtil.bucketName = bucketName;
    }

    @Value("${ali.oss.tempFile}")
    public void setTempFile(String tempFile) {
        AliOssUtil.tempFile = tempFile;
    }
}

5、controller层代码(根据实际业务修改)

@Api(tags = {"A-文件上传controller"})
@RestController
@AllArgsConstructor
public class UploadController {


    @Autowired
    private AliyunConfig aliyunConfig;

    /**
     * 图片上传
     * @param file
     * @return
     */
    @ApiOperation("图片上传")
    @PostMapping("/upload")
    public Result<FileUploadOutVO> upload(@RequestParam("file") MultipartFile file) {
        String fileKey = UUID.randomUUID().toString();
        fileKey = AliOssUtil.upload(fileKey, file);

        FileUploadOutVO upload = new FileUploadOutVO();
        upload.setUrl(fileKey);
        upload.setPrefix(aliyunConfig.getShowUri());
        return Result.success(upload);

    }

    /**
     * 图片回显前置路径
     * @return
     */
    @ApiOperation("图片回显前置路径")
    @GetMapping("/getUrl")
    public Result<FileUploadOutVO> getUrl() {
        FileUploadOutVO upload = new FileUploadOutVO();
        upload.setPrefix(aliyunConfig.getShowUri());
        return Result.success(upload);
    }

}

6、其他配置类

Result
import io.swagger.annotations.ApiModelProperty;
import lombok.*;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
    @ApiModelProperty("响应状态,true-成功,false-其他异常")
    private Boolean success;
    /**
     * 响应码,20000-成功;200001-其他异常
     */
    @ApiModelProperty("响应码,20000-成功; 20001-其他异常")
    private Integer code;
    /**
     * message
     */
    @ApiModelProperty("Message")
    private String message;
    /**
     * 响应数据
     */
    @Getter
    @Setter
    @ApiModelProperty("响应数据")
    private T data;


    public static <T> Result<T> success() {
        return new Result<>(true, 20000, "操作成功", null);
    }

    public static <T> Result<T> success(T data) {
        return new Result<>(true, 20000, "操作成功", data);
    }

    public static <T> Result<T> success(T data, String message) {
        return new Result<>(true, 20000, message, data);
    }

    public static <T> Result<T> success(String message) {
        return new Result<>(true, 20000, message, null);
    }

    public static <T> Result<T> fail() {
        return new Result<>(false, 20001, "操作失败", null);
    }

    public static <T> Result<T> fail(T data) {
        return new Result<>(false, 20001, "操作失败", data);
    }

    public static <T> Result<T> fail(String message, T data) {
        return new Result<>(false, 20001, message, data);
    }

    public static <T> Result<T> fail(Integer code) {
        return new Result<>(false, code, "操作失败", null);
    }

    public static <T> Result<T> fail(Integer code, String message) {
        return new Result<>(false, code, message, null);
    }

    public static <T> Result<T> fail(String message) {
        return new Result<>(false, 20001, message, null);
    }

}

FileUploadOutVO
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

@Data
public class FileUploadOutVO implements Serializable {
    @ApiModelProperty("图片路径")
    private String url;

    @ApiModelProperty("图片回显前置路径")
    private String prefix;

}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值