# 阿里云oss
aliyun:
oss:
# 你的 地域节点
endpoint: oss-cn-beijing.aliyuncs.com
# 你的用户keyId
keyid: 替换成你的
# 你的用户keySecret
keySecret: 替换成你的
# 你的bucket名称
bucketName: 替换成你的
# 你的bucket访问域名
urlPrefix: 替换成你的
配置类
package com.stt.aliyun.oss;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOSSFileConfig {
private String endpoint;
private String keyid;
private String keySecret;
private String bucketName;
private String urlPrefix;
// 这里可以配置你的图片路径前缀
public final static String PRE_TEST = "test/";
}
上传文件
在OSS中,操作的基本数据单元是文件(Object)。OSS Java SDK提供了以下几种文件上传方式:
- 简单上传:包括流式上传和文件上传。最大不能超过5GB。
- 表单上传:最大不能超过5GB。
- 追加上传:最大不能超过5GB。
- 断点续传上传:支持并发、断点续传、自定义分片大小。大文件上传推荐使用断点续传。最大不能超过48.8TB。
- 分片上传:当文件较大时,可以使用分片上传,最大不能超过48.8TB。
创建工具类,实现简单文件上传
package com.stt.aliyun.util.oss;
import com.aliyun.oss.*;
import com.stt.aliyun.config.oss.AliyunOSSFileConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;
@Component
@Slf4j
public class AliyunOSSUtil {
private final AliyunOSSFileConfig aliyunOSSFileConfig;
public AliyunOSSUtil(AliyunOSSFileConfig aliyunOSSFileConfig) {
this.aliyunOSSfileConfig = aliyunOSSFileConfig;
}
/**
* 普通文件上传
* @param file:文件
* @return:上传后的路径
*/
public String exampleUpload(MultipartFile file) {
if(file == null) {
log.error("文件为空");
throw new RuntimeException("请重新上传!");
}
// 设置文件名
String originalFilename = file.getOriginalFilename();
// 获取文件后缀名,也就是文件格式
String fileName = originalFilename.subString(originalFilename.lastIndexOf(".") 1);
// 去除uuid字符串中的-
String uuid = UUID.randomUUID().toString().replaceAll("-","");
// 拼接文件名
fileName = uuid "." fileName;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder()
.build(aliyunOSSFileConfig.getEndpoint(),
aliyunOSSFileConfig.getKeyid(),
aliyunOSSFileConfig.getKeySecret());
try {
// 过输入流上传
ossClient.putObject(aliyunOSSFileConfig.getBucketName(), fileName, file.getInputStream());
} catch (OSSException oe) {
log.error("上传失败===》{}",oe);
} catch (ClientException ce) {
log.error("上传失败===》{}",ce);
} catch (IOException e) {
log.error("上传失败===》{}",e);
throw new RuntimeException(e);
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
// 返回图片访问路径,前端可以回显
return aliyunOSSFileConfig.getUrlPrefix() fileName;
}
}
编写接口
package com.stt.aliyun.controller;
import com.stt.aliyun.util.oss.AliyunOSSUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("aliyun/oss")
public class AliyunOSSController {
private final AliyunOSSUtil aliyunOSSUtil;
public AliyunOSSController(AliyunOSSUtil aliyunOSSUtil) {
this.aliyunOSSUtil = aliyunOSSUtil;
}
// 普通文件上传,返回访问路径
@PostMapping("example")
public String exampleUpload(MultipartFile file) {
return aliyunOSSUtil.exampleUpload(file);
}
}
通过Apifox工具测试,发现图片已经成功上传,而且速度也比较快,秒级响应
上传进度条进度条用于指示上传或下载文件的进度。下方以ossClient.putObject方法为例,介绍上传进度条
自定义监听器实现ProgressListener接口
package com.stt.aliyun.util.oss;
import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.event.ProgressListener;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class AliyunOSSPutProgressListener implements ProgressListener {
// 已上传字节
private long bytesWritten = 0;
// 总大小
private long totalBytes;
// 是否成功
private boolean succeed = false;
// 构造方法,使用时传入上传文件大小
public AliyunOSSPutProgressListener(long totalBytes) {
this.totalBytes = totalBytes;
}
// 进度条修改
public void progressChanged(ProgressEvent progressEvent) {
long bytes = progressEvent.getBytes();
ProgressEventType eventType = progressEvent.getEventType();
switch (eventType) {
case TRANSFER_STARTED_EVENT:
log.info("开始上传");
break;
case REQUEST_CONTENT_LENGTH_EVENT:
this.totalBytes = bytes;
log.info("将要上传{}数据到OSS",this.totalBytes);
break;
case REQUEST_BYTE_TRANSFER_EVENT:
this.bytesWritten = bytes;
// 传入文件总大小
if (this.totalBytes != -1) {
// 计算百分比
int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);
// 将百分比上传到redis或者其他缓存中,前端可以请求获取文件百分比接口获得最新的进度展示
log.info("已上传:{}%",percent);
} else {
// 为传入文件总大小
log.info("已上传{}",this.bytesWritten);
}
break;
case TRANSFER_COMPLETED_EVENT:
this.succeed = true;
log.info("上传完成{} ",this.bytesWritten);
break;
case TRANSFER_FAILED_EVENT:
log.info("上传失败{}",this.bytesWritten);
break;
default:
break;
}
}
// 是否完成
public boolean isSucceed() {
return succeed;
}
}
上传方法
public void progressUpload(MultipartFile file) {
if(file == null) {
log.error("文件为空");
throw new RuntimeException("请重新上传!");
}
OSS ossClient = new OSSClientBuilder()
.build(aliyunOSSFileConfig.getEndpoint(),
aliyunOSSFileConfig.getKeyid(),
aliyunOSSFileConfig.getKeySecret());
try {
String fileName = file.getOriginalFilename();
// 上传文件的同时指定进度条参数。此处PutObjectProgressListenerDemo为调用类的类名,请在实际使用时替换为相应的类名。
PutObjectResult putObjectResult =
ossClient
.putObject(new PutObjectRequest(aliyunOSSFileConfig.getBucketName(), fileName, file.getInputStream())
// 使用上传进度监听器,传入文件大小来计算百分比
.<PutObjectRequest>withProgressListener(new AliyunOSSPutProgressListener(file.getSize())));
} catch (OSSException oe) {
log.error("上传失败===》{}",oe);
} catch (ClientException ce) {
log.error("上传失败===》{}",ce);
} catch (IOException e) {
log.error("上传失败===》{}",e);
throw new RuntimeException(e);
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
接口
@PostMapping("progress")
public void progressUpload(MultipartFile file) {
aliyunOSSUtil.progressUpload(file);
}
通过apifox测试,后台输出百分比
可以将进度存储进缓存,如session,redis等,然后调用另一个接口获取最新的进度在前端展示
删除文件可以根据需要删除单个文件(Object)、删除指定的多个文件、删除指定前缀的文件或者删除指定目录及目录下的所有文件。要删除文件,必须具有oss:DeleteObject权限
请谨慎使用删除操作,文件删除后将无法恢复
删除单个文件public void removeObject(String fileName) {
OSS ossClient = new OSSClientBuilder()
.build(aliyunOSSFileConfig.getEndpoint(),
aliyunOSSFileConfig.getKeyid(),
aliyunOSSFileConfig.getKeySecret());
try {
// 删除文件或目录。如果要删除目录,目录必须为空。
ossClient.deleteObject(aliyunOSSFileConfig.getBucketName(), fileName);
} catch (OSSException oe) {
log.error("删除失败:{}",oe.getMessage());
} catch (ClientException ce) {
log.error("删除失败:{}",ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
测试接口
@DeleteMapping("remove/{filename}")
public String removeObject(@PathVariable("filename") String filename) {
aliyunOSSUtil.removeObject(filename);
return "删除成功";
}
删除选中的文件,将他的文件名传过来就行
测试删除:如果文件名为test.png,该文件在test目录中,则需要带目录传递,即:test/test.png,以此类推