目录

  • 一、对象存储 OSS
  • 二、使用方式
  • 三、开始使用
    • 1、maven依赖
    • 2、配置类:AliyunOssConfig
    • 3、yml配置
    • 4、工具类 AliyunOSSUtil
    • 5、OssController

一、对象存储 OSS

对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

官方学习:https://help.aliyun.com/product/31815.html

二、使用方式

  1. 服务端上传
    这个就是文件经过后台上传,需要注意的是,在使用MultipartFile类时,最大默认1M。需要修改上传文件的大小限制。大文件不推荐这种方式上传。

  2. 服务端签名直传
    意思就是后端生成签名,返回到前端,前端通过签名直接上传到aliyun的oss上,这样可以保证秘钥不可见,提高上传操作的安全性与效率。
    可参考:https://help.aliyun.com/document_detail/31926.html
    这里后端可以设置对应的callback,当成功上传到oss后,oss将上传文件的信息回调给服务端,服务端可以根据回调的url去做后续处理。

三、开始使用

1、maven依赖

首先安装aliyun oss的SDK。
https://help.aliyun.com/document_detail/32009.html

下面使用的maven依赖:

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

2、配置类:AliyunOssConfig

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;/*** @Description: AliyunOssConfig* @Author: qiuyu* @Date: 2021/11/17**/
@Data
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOssConfig {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;private String filePath;@PostConstructpublic void init(){log.debug("oss: endpoint:{},accessKeyId:{},bucketName:{},filePath:{}", endpoint, accessKeyId, bucketName, filePath);}}

3、yml配置

这里注意下,如果是后端上传文件,需要配置spring.servlet.multipart
否则在使用MultipartFile类时,最大默认1M。

aliyun:oss:accessKeyId: L*****************accessKeySecret: s**************bucketName: bucketNameendpoint: oss-cn-hangzhou.aliyuncs.comfilePath: filePath
spring:servlet:multipart:max-file-size: 500MBmax-request-size: 500MB

4、工具类 AliyunOSSUtil

package com.tmzh.saas.sfds.oss.utils;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;@Slf4j
@Component
public class AliyunOSSUtil {private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");private static final long EXPIRTATION_TIME = 60*1000;private static final long CONTENT_LENGTH_RANGE_MIN = 0;private static final long CONTENT_LENGTH_RANGE_MAX = 1024*1024*1000;@Autowiredprivate AliyunOssConfig aliyunOssConfig;private OSS getOssClient() {return new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());}/*** @Description: 判断文件是否存在* @Author: qy* @param fileName: 例如:filePath/fileName**/public boolean isExistFile(String fileName) {OSSClient ossClient = (OSSClient) getOssClient();boolean isExist;try {isExist = ossClient.doesObjectExist(aliyunOssConfig.getBucketName(), fileName);log.info("oss判断文件:{} 是否存在:{}", fileName,isExist);} catch (Exception e) {log.error("oss判断文件存在性异常", e);} finally {ossClient.shutdown();}return isExist;}/*** 上传*/public String upload(MultipartFile file) {OSSClient ossClient = (OSSClient) getOssClient();String fileName = file.getOriginalFilename();log.info("=========>OSS文件上传开始:" + fileName);String datePath = format.format(new Date());try {//容器不存在,就创建if (!ossClient.doesBucketExist(aliyunOssConfig.getBucketName())) {ossClient.createBucket(aliyunOssConfig.getBucketName());CreateBucketRequest createBucketRequest = new CreateBucketRequest(aliyunOssConfig.getBucketName());createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);ossClient.createBucket(createBucketRequest);}// 获取上传的文件的输入流InputStream inputStream = file.getInputStream();//在文件名称里面添加随机唯一值,使用UUID生成// String uuid = UUID.randomUUID().toString().replaceAll("-", "");fileName = aliyunOssConfig.getFilePath() + "/" + datePath + "/" + fileName;// 如果需要上传时设置存储类型与访问权限PutObjectRequest putObjectRequest = new PutObjectRequest(aliyunOssConfig.getBucketName(), fileName, inputStream);ObjectMetadata metadata = new ObjectMetadata();metadata.setContentType(RequestUtil.getContentType(fileName.substring(fileName.lastIndexOf("."))));putObjectRequest.setMetadata(metadata);PutObjectResult result = ossClient.putObject(putObjectRequest);//设置权限 这里是公开读ossClient.setBucketAcl(aliyunOssConfig.getBucketName(), CannedAccessControlList.PublicRead);if (null != result) {String url = "https://" + aliyunOssConfig.getBucketName() + "." + aliyunOssConfig.getEndpoint() + "/" + fileName;log.info("==========>OSS文件上传成功,OSS地址:" + url);return url;}} catch (Exception e) {log.error("oss上传异常", e);} finally {//关闭ossClient.shutdown();}return null;}/*** 删除*/public boolean deleteFile(String fileName) {OSSClient ossClient = (OSSClient) getOssClient();log.info("=========>OSS文件删除开始");try {if (!ossClient.doesBucketExist(aliyunOssConfig.getBucketName())) {log.error("Bucket不存在");}ossClient.deleteObject(aliyunOssConfig.getBucketName(), fileName);log.info("==============>Object删除成功:" + fileName);return true;} catch (Exception e) {log.error("oss删除异常", e);} finally {//关闭ossClient.shutdown();}}/*** @Description: 查询文件名列表* @Author: qy* @param filePath: bucket下的文件路径,例如: filePath/**/public List<String> getObjectList(String filePath) {OSSClient ossClient = (OSSClient) getOssClient();String datePath = format.format(new Date());List<String> listRe = new ArrayList<>();try {log.info("===========>查询文件名列表");ListObjectsRequest listObjectsRequest = new ListObjectsRequest(aliyunOssConfig.getBucketName());// listObjectsRequest.setPrefix(aliyunOssConfig.getFilePath() + "/" + datePath + "/");listObjectsRequest.setPrefix(filePath);ObjectListing list = ossClient.listObjects(listObjectsRequest);// OSSobjectSummary下包含目录下所有的文件,不包含子目录for (OSSObjectSummary objectSummary : list.getObjectSummaries()) {listRe.add(objectSummary.getKey());}return listRe;} catch (Exception ex) {log.error("==========>查询列表失败", ex);return new ArrayList<>();}}/*** @Description: 获取OSS上传Token* @param fileName: aaa.txt**/public Map<String, String> getUploadToken(String fileName) {OSSClient ossClient = (OSSClient) getOssClient();String datePath = format.format(new Date());try{log.info("===========>获取uploadToken");String dir = aliyunOssConfig.getFilePath()+ "/" + datePath +"/";long currentTime = System.currentTimeMillis();String key = dir + fileName.split("\\.")[0] + "-" + currentTime + "." + fileName.split("\\.")[1];long expireEndTime = currentTime + EXPIRTATION_TIME;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, CONTENT_LENGTH_RANGE_MIN, CONTENT_LENGTH_RANGE_MAX);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);//JSONObject jasonCallback = new JSONObject();//你的回调URL//jasonCallback.put("callbackUrl", String.format("%s/callback/imgUploadSuccess", apiDomain));//阿里云回调返回参数//jasonCallback.put("callbackBody", "id=" + id + "&filename=${object}&type=" + type + "&etag=${etag}&size=${size}&height=${imageInfo.height}&width=${imageInfo.width}&mimeType=${mimeType}");//asonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");//String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());Map<String, String> res = new HashMap<>();//res.put("callback", base64CallbackBody);res.put("key", key); //dir + fileName (上传Object的名称。)res.put("OSSAccessKeyId", aliyunOssConfig.getAccessKeyId());res.put("policy", encodedPolicy); //Policy规定了请求表单域的合法性。res.put("signature", postSignature); //根据AccessKey Secret和Policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性。res.put("dir", dir); //前缀res.put("uploadUrl", "https://" + aliyunOssConfig.getBucketName() + "." + aliyunOssConfig.getEndpoint()); // "https://" + bucketname + '.' + endpoint;  (前端请求oss服务路径)res.put("expire", String.valueOf(expireEndTime / 1000));res.put("success_action_status", "200");log.debug("res:{}",res);return res;}catch (Exception e){log.error("==========>获取uploadToken失败", e);}finally {ossClient.shutdown();}return null;}}

5、OssController

@RestController
@Api(tags = "OSS模块")
@RequestMapping("/oss/file")
public class OssController extends BaseController{@Autowiredprivate AliyunOSSUtil aliyunOSSUtil;@PostMapping("/upload")@ApiOperation(value = "上传")@ApiImplicitParams({@ApiImplicitParam(paramType = "form", dataType = "MultipartFile", dataTypeClass = MultipartFile.class, name = "file",value = "文件", required = true)})public ResponseEntity<Result> upload(@RequestParam("file") MultipartFile multipartFile) {return ok(aliyunOSSUtil.upload(multipartFile));}@GetMapping("/list")@ApiOperation(value = "文件列表")@ApiImplicitParams({@ApiImplicitParam(paramType = "query", dataType = "String", dataTypeClass = String.class, name = "filePath",value = "bucket下的文件路径,例如: filePath/", required = true)})public ResponseEntity<Result> list(@RequestParam("filePath") String filePath) {return ok(aliyunOSSUtil.getObjectList(filePath));}@GetMapping("/isExist")@ApiOperation(value = "判断文件是否存在")@ApiImplicitParams({@ApiImplicitParam(paramType = "query", dataType = "String", dataTypeClass = String.class, name = "fileName",value = "例如:filePath/fileName", required = true)})public ResponseEntity<Result> isExist(@RequestParam("fileName") String fileName) {return ok(aliyunOSSUtil.isExistFile(fileName));}@DeleteMapping("/delete")@ApiOperation(value = "删除文件")@ApiImplicitParams({@ApiImplicitParam(paramType = "query", dataType = "String", dataTypeClass = String.class, name = "fileName",value = "例如:filePath/fileName", required = true)})public ResponseEntity<Result> delete(@RequestParam("fileName") String fileName) {return ok(aliyunOSSUtil.deleteFile(fileName));}/*** @Description: 服务端签名直传**/@PostMapping("/uploadToken")@ApiOperation(value = "获取uploadToken")@ApiImplicitParams({@ApiImplicitParam(paramType = "form", dataType = "String", dataTypeClass = String.class, name = "fileName",value = "文件名", required = true)})public ResponseEntity<Result> uploadToken(@RequestParam("fileName") String fileName) {return ok(aliyunOSSUtil.getUploadToken(fileName));}}

springboot中使用aliyun的oss相关推荐

  1. SpringBoot集成阿里云存储OSS服务

    前言 该文章会先简单的介绍一下阿里云的OSS存储,然后演示如何在SpringBoot项目中集成OSS,每一步都有记录,保证初学者也能看懂. 文章目录 前言 1.阿里云存储OSS是什么? 2.Sprin ...

  2. springboot中druid数据源配置无效的问题和jar包找不到问题

    springboot中druid数据源配置无效的问题 阿里云的仓库 链接: 阿里云仓库. 自己在springboot项目中,引入druid的依赖,希望引入druid数据源. 但是idea中,虽然在这个 ...

  3. SpringBoot中静态变量注入方案,一网打尽

    前言 同事来找我,说自己想使用@Value注解来注入值,但是发现注入不进去,想让我帮忙看看.研究了一番,最后发现是@Value注解无法注入静态变量.下面我们一起来回顾一下本次的bug. 普通变量 首先 ...

  4. 在SpringBoot中使用Spring Session解决分布式会话共享问题

    在SpringBoot中使用Spring Session解决分布式会话共享问题 问题描述: 每次当重启服务器时,都会导致会员平台中已登录的用户掉线.这是因为每个用户的会话信息及状态都是由session ...

  5. SpringBoot 中 JPA 的使用

    前言 第一次使用 Spring JPA 的时候,感觉这东西简直就是神器,几乎不需要写什么关于数据库访问的代码一个基本的 CURD 的功能就出来了.下面我们就用一个例子来讲述以下 JPA 使用的基本操作 ...

  6. 难以想象SpringBoot中的条件注解底层居然是这样实现的

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源 | https://urlify.cn/bm2qqi Spr ...

  7. 面试:SpringBoot中的条件注解底层是如何实现的?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源 | https://urlify.cn/bm2qqi Spr ...

  8. springboot yml怎么建常量_【Java】SpringBoot 中从application.yml中获取自定义常量

    由于这里我想通过java连接linux,connection连接需要host.port.username.password及其他路径等等.不想每次修改的时候都去改源文件,所以想写在applicatio ...

  9. Springboot中给图片添加文字水印

    Springboot中给图片添加文字水印 工作中遇到给图片添加文字水印的需求,记录下来方便之后查阅 需求内容: 给一张图片添加指定文字水印,使一张图片上有多个水印内容,并且设定一个水印开关,可指定是否 ...

最新文章

  1. mysql 不让读的锁_MySQL实战45讲阅读笔记-锁
  2. 越卖越涨?腾讯股票3月后大涨45%,超越“阿里”成中国第一,市值相当于14.3个百度!...
  3. STM32 USB-HID通信移植步骤
  4. 320. Generalized Abbreviation-- back tracking and bit manipulation(待续)
  5. 【C 语言】数组作为参数退化为指针问题 ( 问题描述 | 从编译器角度分析该问题 | 出于提高 C 语言执行效率角度考虑 | 数组作为参数的推荐方案 )
  6. 【洛谷 3372】线段树 1
  7. 公式 有效值_纯电阻电路电功率公式
  8. 有朋友问我为什么这么帅
  9. CPU:别再拿我当搬砖工!
  10. 信息学奥赛一本通 1412:二进制分类 | OpenJudge NOI 1.13 36:二进制分类
  11. 【英语学习】【WOTD】abecedarian 释义/词源/示例
  12. 基于JAVA+SpringBoot+Mybatis+MYSQL的记账本管理系统
  13. 阿里巴巴十周年庆(预告)
  14. V4L2视频采集与H264编码4—X264编码H264视频
  15. 关于DllRegisterServer的调用失败的问题解决办法 错误代码0x80040201
  16. fseek(f,0,SEEK_SET);
  17. kpi绩效考核流程图_KPI绩效考核如何运作起来(内含企业KPI实例之详解)
  18. PADS如何导出BOM清单
  19. 3.JDBC基础代码书写
  20. android实习日志_2016年3月8日Android实习日记

热门文章

  1. 频率在电子领域内,频率是一种最基本的参数,并与其他许多电参量的测量方案和测量结果都有着十分密切的关系。由于频率信号抗干扰能力强、易于传输,可以获得较高的测量精度。因此,频率的测量就显得尤为重要,测频方
  2. 大数据量查询解决方案
  3. 如何恢复移动硬盘数据删除的文件
  4. 2021年Java发展怎么样?现在学了Java技术出来是否还能找到工作?
  5. nginx开启Gzip压缩,Vue性能优化之使用gzip压缩打包
  6. 网络安全学习路线-超详细
  7. ios CAShapeLayer
  8. SSH命令行使用方法
  9. 【黄啊码】PHP压缩图片(简洁易懂版,不懂我下次不写)
  10. error: variable '__this_module' has initializer but incomplete type错误解决