oss模块
This commit is contained in:
parent
4a4c23f310
commit
9c7549a3e8
10
ruoyi-admin/src/main/resources/application-oss.yml
Normal file
10
ruoyi-admin/src/main/resources/application-oss.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# oss配置
|
||||||
|
oss:
|
||||||
|
enable: false
|
||||||
|
primary: MASTER
|
||||||
|
client:
|
||||||
|
MASTER:
|
||||||
|
accessKeyId:
|
||||||
|
accessKeySecret:
|
||||||
|
bucketName: szb-resource
|
||||||
|
endpoint: oss-cn-shenzhen.aliyuncs.com
|
@ -12,7 +12,7 @@ ruoyi:
|
|||||||
addressEnabled: false
|
addressEnabled: false
|
||||||
# 验证码类型 math 数组计算 char 字符验证
|
# 验证码类型 math 数组计算 char 字符验证
|
||||||
captchaType: math
|
captchaType: math
|
||||||
# 指定默认文件服务类型(值为disk代表使用磁盘作为文件操作服务,minio代表使用minio作为文件操作服务)
|
# 指定默认文件服务类型(值为disk代表使用磁盘作为文件操作服务,minio代表使用minio作为文件操作服务,oss代表使用oss作为文件操作服务)
|
||||||
fileServer: disk
|
fileServer: disk
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
@ -69,7 +69,7 @@ spring:
|
|||||||
# 国际化资源文件路径
|
# 国际化资源文件路径
|
||||||
basename: i18n/messages
|
basename: i18n/messages
|
||||||
profiles:
|
profiles:
|
||||||
active: druid,mybatis,auth,pay,middleware,lp
|
active: druid,mybatis,auth,pay,middleware,lp,oss
|
||||||
# 文件上传
|
# 文件上传
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
<ehcache.version>3.10.8</ehcache.version>
|
<ehcache.version>3.10.8</ehcache.version>
|
||||||
<mybatis-plus.version>3.5.8</mybatis-plus.version>
|
<mybatis-plus.version>3.5.8</mybatis-plus.version>
|
||||||
<netty.version>4.1.112.Final</netty.version>
|
<netty.version>4.1.112.Final</netty.version>
|
||||||
|
<oss.version>3.18.1</oss.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<description>
|
<description>
|
||||||
@ -87,6 +88,20 @@
|
|||||||
<version>${netty.version}</version>
|
<version>${netty.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- alibaba-oss -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-alibaba-oss</artifactId>
|
||||||
|
<version>${ruoyi.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- oss-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>${oss.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
@ -99,6 +114,7 @@
|
|||||||
<module>ruoyi-plugins-starter</module>
|
<module>ruoyi-plugins-starter</module>
|
||||||
<module>ruoyi-mybatis-interceptor</module>
|
<module>ruoyi-mybatis-interceptor</module>
|
||||||
<module>ruoyi-netty</module>
|
<module>ruoyi-netty</module>
|
||||||
|
<module>ruoyi-alibaba-oss</module>
|
||||||
</modules>
|
</modules>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
</project>
|
</project>
|
||||||
|
28
ruoyi-plugins/ruoyi-alibaba-oss/pom.xml
Normal file
28
ruoyi-plugins/ruoyi-alibaba-oss/pom.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>ruoyi-plugins</artifactId>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<version>3.8.8.3.1</version>
|
||||||
|
</parent>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-alibaba-oss</artifactId>
|
||||||
|
<description>oss中间件</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--阿里云oss-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>3.10.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,135 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.aliyun.oss.ClientException;
|
||||||
|
import com.aliyun.oss.OSS;
|
||||||
|
import com.aliyun.oss.OSSClientBuilder;
|
||||||
|
import com.aliyun.oss.OSSException;
|
||||||
|
import com.ruoyi.alibaba.oss.domain.AliOssBucket;
|
||||||
|
|
||||||
|
@Configuration("AliOssConfiguration")
|
||||||
|
@ConditionalOnProperty(prefix = "oss", name = "enable", havingValue = "true", matchIfMissing = false)
|
||||||
|
@ConfigurationProperties(prefix = "oss")
|
||||||
|
public class AliOssConfig implements InitializingBean {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AliOssConfig.class);
|
||||||
|
public static int maxSize;
|
||||||
|
private String prefix = "/oss"; // 根据需要调整前缀
|
||||||
|
private Map<String, AliOssProperties> client = new HashMap<>();
|
||||||
|
private String primary;
|
||||||
|
private Map<String, AliOssBucket> targetAliOssBucket = new HashMap<>();
|
||||||
|
private AliOssBucket masterBucket;
|
||||||
|
|
||||||
|
public int getMaxSize() {
|
||||||
|
return maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AliOssBucket getMasterBucket() {
|
||||||
|
return this.masterBucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AliOssBucket getBucket(String client) {
|
||||||
|
return targetAliOssBucket.get(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, AliOssProperties> getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(Map<String, AliOssProperties> client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrimary() {
|
||||||
|
return primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrimary(String primary) {
|
||||||
|
this.primary = primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrefix(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
if (client == null || client.isEmpty()) {
|
||||||
|
throw new RuntimeException("Client properties cannot be null or empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
client.forEach((name, props) -> {
|
||||||
|
try {
|
||||||
|
AliOssBucket aliOssBucket = createOssClient(name, props);
|
||||||
|
targetAliOssBucket.put(name, aliOssBucket);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Failed to create OSS client for {}: {}", name, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (targetAliOssBucket.get(primary) == null) {
|
||||||
|
throw new RuntimeException("Primary client " + primary + " does not exist");
|
||||||
|
}
|
||||||
|
masterBucket = targetAliOssBucket.get(primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AliOssBucket createOssClient(String name, AliOssProperties props) {
|
||||||
|
if (props == null || props.getEndpoint() == null || props.getAccessKeyId() == null ||
|
||||||
|
props.getAccessKeySecret() == null || props.getBucketName() == null) {
|
||||||
|
throw new IllegalArgumentException("AliOssProperties or its required fields cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
OSS client = new OSSClientBuilder().build(props.getEndpoint(), props.getAccessKeyId(), props.getAccessKeySecret());
|
||||||
|
AliOssBucket ossBucket = new AliOssBucket(client, props.getBucketName());
|
||||||
|
validateOssBucket(ossBucket);
|
||||||
|
logger.info("数据桶:{} - 链接成功", name);
|
||||||
|
return ossBucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateOssBucket(AliOssBucket aliOssBucket) {
|
||||||
|
OSS ossClient = aliOssBucket.getOssClient();
|
||||||
|
String bucketName = aliOssBucket.getBucketName();
|
||||||
|
try {
|
||||||
|
if (!ossClient.doesBucketExist(bucketName)) {
|
||||||
|
throw new RuntimeException("Bucket " + bucketName + " does not exist");
|
||||||
|
}
|
||||||
|
} catch (OSSException oe) {
|
||||||
|
logger.error("OSSException: " + oe.getMessage(), oe);
|
||||||
|
throw new RuntimeException("OSS error: " + oe.getMessage());
|
||||||
|
} catch (ClientException ce) {
|
||||||
|
logger.error("ClientException: " + ce.getMessage(), ce);
|
||||||
|
throw new RuntimeException("Client error: " + ce.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Exception: " + e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Error validating OSS bucket: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getMasterBucketName() {
|
||||||
|
if (masterBucket != null) {
|
||||||
|
return masterBucket.getBucketName();
|
||||||
|
}
|
||||||
|
return null; // 或者抛出异常,根据业务需求决定
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBucketName(String client) {
|
||||||
|
if (client != null && targetAliOssBucket.containsKey(client)) {
|
||||||
|
return targetAliOssBucket.get(client).getBucketName();
|
||||||
|
}
|
||||||
|
return null; // 或者抛出异常,根据业务需求决定
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import com.aliyun.oss.OSSClient;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "oss.client")
|
||||||
|
public class AliOssProperties {
|
||||||
|
|
||||||
|
private String endpoint;
|
||||||
|
private String accessKeyId;
|
||||||
|
private String accessKeySecret;
|
||||||
|
private String bucketName;
|
||||||
|
|
||||||
|
private OSSClient ossClient;
|
||||||
|
|
||||||
|
public AliOssProperties(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public AliOssProperties(String endpoint, String accessKeyId, String accessKeySecret, String bucketName) {
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
this.accessKeyId = accessKeyId;
|
||||||
|
this.accessKeySecret = accessKeySecret;
|
||||||
|
this.bucketName = bucketName;
|
||||||
|
}
|
||||||
|
public String getEndpoint() {
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
public void setEndpoint(String endpoint) {
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
}
|
||||||
|
public String getAccessKeyId() {
|
||||||
|
return accessKeyId;
|
||||||
|
}
|
||||||
|
public void setAccessKeyId(String accessKeyId) {
|
||||||
|
this.accessKeyId = accessKeyId;
|
||||||
|
}
|
||||||
|
public String getAccessKeySecret() {
|
||||||
|
return accessKeySecret;
|
||||||
|
}
|
||||||
|
public void setAccessKeySecret(String accessKeySecret) {
|
||||||
|
this.accessKeySecret = accessKeySecret;
|
||||||
|
}
|
||||||
|
public String getBucketName() {
|
||||||
|
return bucketName;
|
||||||
|
}
|
||||||
|
public void setBucketName(String bucketName) {
|
||||||
|
this.bucketName = bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OSSClient getOssClient() {
|
||||||
|
return ossClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOssClient(OSSClient ossClient) {
|
||||||
|
this.ossClient = ossClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.controller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.ruoyi.alibaba.oss.domain.AliOssFileVO;
|
||||||
|
import com.ruoyi.alibaba.oss.utils.AliOssUtil;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/oss")
|
||||||
|
public class AliOssController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AliOssUtil aliOssUtil;
|
||||||
|
|
||||||
|
@Operation(summary = "下载接口oss")
|
||||||
|
@GetMapping("/{client}")
|
||||||
|
public void downLoadFile(HttpServletRequest request, HttpServletResponse response,@PathVariable("client") String client,
|
||||||
|
@RequestParam("fileName") String fileName) throws Exception {
|
||||||
|
AliOssFileVO file = aliOssUtil.getFile(client, fileName);
|
||||||
|
// 设置响应头
|
||||||
|
String contentType = file.getHeaders().getOrDefault("Content-Type", "application/octet-stream");
|
||||||
|
response.setContentType(contentType);
|
||||||
|
|
||||||
|
// 设置内容长度
|
||||||
|
String contentLength = file.getHeaders().get("Content-Length");
|
||||||
|
if (contentLength != null) {
|
||||||
|
response.setContentLengthLong(Long.parseLong(contentLength));
|
||||||
|
}
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
|
||||||
|
// 写入文件内容到响应流
|
||||||
|
try (InputStream inputStream = file.getFileInputSteam();
|
||||||
|
OutputStream outputStream = response.getOutputStream()) {
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
outputStream.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IOException("Error writing file to output stream", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//上传接口
|
||||||
|
@Operation(summary = "上传接口oss")
|
||||||
|
@PutMapping("/{client}")
|
||||||
|
public String uploadFile(HttpServletRequest request, HttpServletResponse response,
|
||||||
|
@PathVariable("client") String client, @RequestParam("file") MultipartFile file) throws Exception {
|
||||||
|
return AliOssUtil.uploadFile(client, file);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.domain;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.aliyun.oss.OSS;
|
||||||
|
import com.aliyun.oss.model.DeleteObjectsRequest;
|
||||||
|
import com.aliyun.oss.model.GetObjectRequest;
|
||||||
|
import com.aliyun.oss.model.OSSObject;
|
||||||
|
import com.aliyun.oss.model.ObjectMetadata;
|
||||||
|
import com.aliyun.oss.model.PutObjectRequest;
|
||||||
|
import com.ruoyi.alibaba.oss.exception.AliOssClientErrorException;
|
||||||
|
|
||||||
|
public class AliOssBucket {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AliOssBucket.class);
|
||||||
|
|
||||||
|
private String bucketName;
|
||||||
|
private OSS ossClient;
|
||||||
|
|
||||||
|
public AliOssBucket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造函数
|
||||||
|
public AliOssBucket(OSS ossClient, String bucketName) {
|
||||||
|
this.ossClient = ossClient;
|
||||||
|
this.bucketName = bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OSS getOssClient() {
|
||||||
|
return ossClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOssClient(OSS ossClient) {
|
||||||
|
this.ossClient = ossClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBucketName() {
|
||||||
|
return bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBucketName(String bucketName) {
|
||||||
|
this.bucketName = bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String fileName, MultipartFile file) throws Exception {
|
||||||
|
put(fileName, file.getContentType(), file.getInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
public void put(String filePath, String contentType, InputStream inputStream) throws Exception {
|
||||||
|
try {
|
||||||
|
// 创建 ObjectMetadata 对象,并设置内容类型
|
||||||
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
|
metadata.setContentType(contentType);
|
||||||
|
metadata.setContentLength(inputStream.available()); // 使用 InputStream 的 available 方法
|
||||||
|
|
||||||
|
// 创建 PutObjectRequest 对象
|
||||||
|
PutObjectRequest putRequest = new PutObjectRequest(bucketName, filePath, inputStream, metadata);
|
||||||
|
|
||||||
|
// 上传对象
|
||||||
|
ossClient.putObject(putRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error uploading file: {}", e.getMessage(), e);
|
||||||
|
throw new AliOssClientErrorException("Error uploading file: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(PutObjectRequest putObjectRequest) throws Exception {
|
||||||
|
try {
|
||||||
|
this.ossClient.putObject(putObjectRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error uploading file: {}", e.getMessage(), e);
|
||||||
|
throw new AliOssClientErrorException("Error uploading file: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(String filePath) throws Exception {
|
||||||
|
// 删除单个对象
|
||||||
|
ossClient.deleteObject(bucketName, filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMultiple(List<String> filePaths) throws Exception {
|
||||||
|
// 删除多个对象
|
||||||
|
try {
|
||||||
|
DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName).withKeys(filePaths);
|
||||||
|
ossClient.deleteObjects(deleteRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error deleting files: {}", e.getMessage(), e);
|
||||||
|
throw new AliOssClientErrorException("Error deleting files: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AliOssFileVO get(GetObjectRequest getObjectRequest) throws Exception {
|
||||||
|
try (OSSObject ossObject = this.ossClient.getObject(getObjectRequest)) {
|
||||||
|
if (ossObject == null) {
|
||||||
|
throw new Exception("Failed to retrieve object from OSS.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取OSSObject的内容到ByteArrayOutputStream中
|
||||||
|
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||||
|
byte[] bytes = new byte[1024]; // 根据需要调整缓冲区大小
|
||||||
|
int length;
|
||||||
|
while ((length = ossObject.getObjectContent().read(bytes)) != -1) {
|
||||||
|
byteArrayOutputStream.write(bytes, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 headers
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
for (Map.Entry<String, String> entry : ossObject.getObjectMetadata().getUserMetadata().entrySet()) {
|
||||||
|
headers.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
headers.put("Content-Type", ossObject.getObjectMetadata().getContentType());
|
||||||
|
headers.put("Content-Length", String.valueOf(ossObject.getObjectMetadata().getContentLength()));
|
||||||
|
|
||||||
|
// 设置 AliOssFileVO 对象的属性
|
||||||
|
AliOssFileVO fileVO = new AliOssFileVO();
|
||||||
|
fileVO.setFileInputSteam(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
|
||||||
|
fileVO.setHeaders(headers);
|
||||||
|
fileVO.setKey(ossObject.getKey());
|
||||||
|
fileVO.setBucketName(ossObject.getBucketName());
|
||||||
|
|
||||||
|
return fileVO;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error retrieving file: {}", e.getMessage(), e);
|
||||||
|
throw new AliOssClientErrorException("Error retrieving file: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载
|
||||||
|
*
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @return 返回封装的OSS下载文件对象
|
||||||
|
* @throws Exception 如果下载过程中出现问题
|
||||||
|
*/
|
||||||
|
public AliOssFileVO get(String filePath) throws Exception {
|
||||||
|
GetObjectRequest request = new GetObjectRequest(this.bucketName, filePath);
|
||||||
|
return get(request);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.domain;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AliOssFileVO {
|
||||||
|
private InputStream fileInputSteam;
|
||||||
|
private String key;
|
||||||
|
private Map<String, String> headers;
|
||||||
|
private String bucketName;
|
||||||
|
|
||||||
|
public AliOssFileVO(){}
|
||||||
|
|
||||||
|
public AliOssFileVO(InputStream fileInputSteam, String key, Map<String, String> headers, String bucketName) {
|
||||||
|
this.fileInputSteam = fileInputSteam;
|
||||||
|
this.key = key;
|
||||||
|
this.headers = headers;
|
||||||
|
this.bucketName = bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getFileInputSteam() {
|
||||||
|
return fileInputSteam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileInputSteam(InputStream fileInputSteam) {
|
||||||
|
this.fileInputSteam = fileInputSteam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeaders() {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaders(Map<String, String> headers) {
|
||||||
|
this.headers = headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBucketName() {
|
||||||
|
return bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBucketName(String bucketName) {
|
||||||
|
this.bucketName = bucketName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.exception;
|
||||||
|
|
||||||
|
public class AliOssClientErrorException extends RuntimeException{
|
||||||
|
public AliOssClientErrorException(String msg){
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AliOssClientErrorException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.exception;
|
||||||
|
|
||||||
|
public class AliOssClientNotFundException extends RuntimeException{
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.ruoyi.alibaba.oss.config.AliOssConfig;
|
||||||
|
import com.ruoyi.alibaba.oss.domain.AliOssFileVO;
|
||||||
|
import com.ruoyi.alibaba.oss.utils.AliOssUtil;
|
||||||
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.service.file.FileService;
|
||||||
|
import com.ruoyi.common.utils.file.FileOperateUtils;
|
||||||
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oss文件操作实现类
|
||||||
|
*/
|
||||||
|
@Component("file:strategy:oss")
|
||||||
|
@ConditionalOnProperty(prefix = "oss", name = { "enable" }, havingValue = "true", matchIfMissing = false)
|
||||||
|
public class AliOssFileService implements FileService {
|
||||||
|
@Autowired
|
||||||
|
private AliOssConfig aliOssConfig;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String upload(String filePath, MultipartFile file) throws Exception {
|
||||||
|
String relativePath = null;
|
||||||
|
if (FileUtils.isAbsolutePath(filePath)) {
|
||||||
|
relativePath = FileUtils.getRelativePath(filePath);
|
||||||
|
} else {
|
||||||
|
relativePath = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fullPath = AliOssUtil.uploadFile(aliOssConfig.getPrimary(), relativePath, file);
|
||||||
|
return extractFileName(fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String upload(MultipartFile file, String name) throws Exception {
|
||||||
|
String fullPath = AliOssUtil.uploadFile(aliOssConfig.getPrimary(), name, file);
|
||||||
|
return extractFileName(fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String upload(MultipartFile file) throws Exception {
|
||||||
|
String filePath = RuoYiConfig.getProfile() + File.separator + FileUtils.fastFilePath(file);
|
||||||
|
return upload(filePath, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String upload(String baseDir, String fileName, MultipartFile file) throws Exception {
|
||||||
|
return upload(baseDir + File.pathSeparator + fileName, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream downLoad(String filepath) throws Exception {
|
||||||
|
AliOssFileVO file = AliOssUtil.getFile(filepath);
|
||||||
|
return file.getFileInputSteam();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFile(String fileUrl) throws Exception {
|
||||||
|
AliOssUtil.removeFile(aliOssConfig.getPrimary(), fileUrl);
|
||||||
|
FileOperateUtils.deleteFileAndMd5ByFilePath(fileUrl);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取文件名
|
||||||
|
*
|
||||||
|
* @param fullPath 完整的文件路径
|
||||||
|
* @return 文件名
|
||||||
|
*/
|
||||||
|
private String extractFileName(String fullPath) {
|
||||||
|
if (fullPath == null || !fullPath.contains("fileName=")) {
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
int startIndex = fullPath.indexOf("fileName=") + "fileName=".length();
|
||||||
|
if (startIndex < 0 || startIndex >= fullPath.length()) {
|
||||||
|
return fullPath; // 如果没有找到 "fileName=",则返回原路径
|
||||||
|
}
|
||||||
|
return fullPath.substring(startIndex);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,182 @@
|
|||||||
|
package com.ruoyi.alibaba.oss.utils;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.aliyun.oss.OSS;
|
||||||
|
import com.aliyun.oss.model.GetObjectRequest;
|
||||||
|
import com.aliyun.oss.model.OSSObject;
|
||||||
|
import com.ruoyi.alibaba.oss.config.AliOssConfig;
|
||||||
|
import com.ruoyi.alibaba.oss.domain.AliOssBucket;
|
||||||
|
import com.ruoyi.alibaba.oss.domain.AliOssFileVO;
|
||||||
|
import com.ruoyi.alibaba.oss.exception.AliOssClientErrorException;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import com.ruoyi.common.utils.uuid.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oss工具
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AliOssUtil {
|
||||||
|
|
||||||
|
private static AliOssConfig aliOssConfig;
|
||||||
|
|
||||||
|
private static AliOssConfig getAliOssConfig() {
|
||||||
|
if (aliOssConfig == null) {
|
||||||
|
synchronized (AliOssUtil.class) {
|
||||||
|
if (aliOssConfig == null) {
|
||||||
|
aliOssConfig = SpringUtils.getBean(AliOssConfig.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aliOssConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传
|
||||||
|
*
|
||||||
|
* @param client 连接名
|
||||||
|
* @param file 上传的文件
|
||||||
|
* @return 返回上传成功的文件名
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
*/
|
||||||
|
public static String uploadFile(String client, MultipartFile file) throws Exception {
|
||||||
|
String fileName = DateUtils.dateTimeNow() + UUID.fastUUID().toString().substring(0, 5) + "." + FileUtils.getExtension(file);
|
||||||
|
return uploadFile(client, fileName, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传
|
||||||
|
*
|
||||||
|
* @param client 连接名
|
||||||
|
* @param fileName 上传文件名
|
||||||
|
* @param file 上传的文件
|
||||||
|
* @return 返回上传成功的文件名
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
*/
|
||||||
|
public static String uploadFile(String client, String fileName, MultipartFile file) throws Exception {
|
||||||
|
getAliOssConfig().getBucket(client).put(fileName, file);
|
||||||
|
return getURL(client, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件URL
|
||||||
|
*
|
||||||
|
* @param client 连接名
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @return 返回上传成功的文件路径
|
||||||
|
*/
|
||||||
|
public static String getURL(String client, String filePath) throws Exception {
|
||||||
|
try {
|
||||||
|
StringBuilder url = new StringBuilder();
|
||||||
|
url.append(getAliOssConfig().getPrefix()).append("/").append(client)
|
||||||
|
.append("?").append("fileName=").append(filePath);
|
||||||
|
return url.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AliOssClientErrorException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件删除
|
||||||
|
*
|
||||||
|
* @param filePath 上传文件路径
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
*/
|
||||||
|
public static void removeFile(String filePath) throws Exception {
|
||||||
|
getAliOssConfig().getMasterBucket().remove(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件删除
|
||||||
|
*
|
||||||
|
* @param client 连接名
|
||||||
|
* @param filePath 上传文件路径
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
*/
|
||||||
|
public static void removeFile(String client, String filePath) throws Exception {
|
||||||
|
getAliOssConfig().getBucket(client).remove(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载
|
||||||
|
*
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @return 返回封装的Oss下载文件对象
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
*/
|
||||||
|
public static AliOssFileVO getFile(String filePath) throws Exception {
|
||||||
|
return getFile(null, filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载
|
||||||
|
*
|
||||||
|
* @param client 连接名
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @return 返回封装的Oss下载文件对象
|
||||||
|
* @throws IOException 比如读写文件出错时
|
||||||
|
*/
|
||||||
|
public static AliOssFileVO getFile(String client, String filePath) throws Exception {
|
||||||
|
AliOssBucket ossBucket = client == null ? getAliOssConfig().getMasterBucket() : getAliOssConfig().getBucket(client);
|
||||||
|
String bucketName = client == null ? getAliOssConfig().getMasterBucketName() : getAliOssConfig().getBucketName(client);
|
||||||
|
|
||||||
|
if (bucketName == null) {
|
||||||
|
throw new AliOssClientErrorException("参数 \"bucketName\" 为空指针");
|
||||||
|
}
|
||||||
|
|
||||||
|
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, filePath);
|
||||||
|
|
||||||
|
return get(getObjectRequest, ossBucket.getOssClient());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 从OSS中获取文件并封装成AliOssFileVO对象
|
||||||
|
*
|
||||||
|
* @param getObjectRequest 获取对象请求
|
||||||
|
* @param ossClient OSS客户端
|
||||||
|
* @return 返回封装的Oss下载文件对象
|
||||||
|
* @throws Exception 如果获取文件失败
|
||||||
|
*/
|
||||||
|
private static AliOssFileVO get(GetObjectRequest getObjectRequest, OSS ossClient) throws Exception {
|
||||||
|
OSSObject ossObject = ossClient.getObject(getObjectRequest);
|
||||||
|
if (ossObject == null) {
|
||||||
|
throw new Exception("Failed to retrieve object from OSS.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取OSSObject的内容到ByteArrayOutputStream中
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
byte[] bytes = new byte[1024]; // 根据需要调整缓冲区大小
|
||||||
|
int length;
|
||||||
|
while ((length = ossObject.getObjectContent().read(bytes)) != -1) {
|
||||||
|
byteArrayOutputStream.write(bytes, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 headers
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
for (Map.Entry<String, String> entry : ossObject.getObjectMetadata().getUserMetadata().entrySet()) {
|
||||||
|
headers.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
headers.put("Content-Type", ossObject.getObjectMetadata().getContentType());
|
||||||
|
headers.put("Content-Length", String.valueOf(ossObject.getObjectMetadata().getContentLength()));
|
||||||
|
|
||||||
|
// 设置 AliOssFileVO 对象的属性
|
||||||
|
AliOssFileVO fileVO = new AliOssFileVO();
|
||||||
|
fileVO.setFileInputSteam(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
|
||||||
|
fileVO.setHeaders(headers);
|
||||||
|
fileVO.setKey(ossObject.getKey());
|
||||||
|
fileVO.setBucketName(ossObject.getBucketName());
|
||||||
|
|
||||||
|
// 关闭OSSObject
|
||||||
|
ossObject.close();
|
||||||
|
|
||||||
|
return fileVO;
|
||||||
|
}
|
||||||
|
}
|
@ -55,6 +55,12 @@
|
|||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-netty</artifactId>
|
<artifactId>ruoyi-netty</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--oss配置-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-alibaba-oss</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
Loading…
Reference in New Issue
Block a user