新增文件上传模块

🐛 修复日志记录开关以及文件上传时由于日志记录导致的文件读取异常
This commit is contained in:
b2baccline
2020-01-09 13:09:03 +08:00
parent f4ea5d5a08
commit a9490d9b63
24 changed files with 380 additions and 33 deletions

View File

@@ -45,7 +45,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -59,6 +59,11 @@ public enum ResultStatus {
*/
MALICIOUS_REQUEST(90002, "Malicious Request"),
/**
* 文件上传异常
*/
FILE_UPLOAD_ERROR(90003, "File Upload Error"),
/**
* 未知异常
*/

View File

@@ -17,10 +17,6 @@
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>

View File

@@ -2,6 +2,7 @@ package com.hccake.ballcat.commom.log.access.filter;
import cn.hutool.core.util.StrUtil;
import com.hccake.ballcat.commom.log.access.service.AccessLogHandlerService;
import com.hccake.ballcat.commom.log.util.LogUtils;
import com.hccake.ballcat.common.core.filter.RepeatBodyRequestWrapper;
import lombok.AllArgsConstructor;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -36,12 +37,20 @@ public class AccessLogFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 排除监控请求 TODO 可配置
if (StrUtil.containsAnyIgnoreCase(request.getRequestURI(),"/actuator")){
if (StrUtil.containsAnyIgnoreCase(request.getRequestURI(), "/actuator")) {
filterChain.doFilter(request, response);
return;
}
// 包装request以保证可以重复读取body
RepeatBodyRequestWrapper requestWrapper = new RepeatBodyRequestWrapper(request);
// 包装request以保证可以重复读取body 但不对文件上传请求body进行处理
HttpServletRequest requestWrapper;
if (LogUtils.isMultipartContent(request)) {
requestWrapper = request;
}else {
requestWrapper = new RepeatBodyRequestWrapper(request);
}
// 开始时间
Long startTime = System.currentTimeMillis();
@@ -68,4 +77,7 @@ public class AccessLogFilter extends OncePerRequestFilter {
}
}

View File

@@ -52,4 +52,20 @@ public class LogUtils {
return body;
}
/**
* 判断是否是multipart/form-data请求
*
* @param request
* @return
*/
public static boolean isMultipartContent(HttpServletRequest request) {
if (!HttpMethod.POST.name().equals(request.getMethod().toUpperCase())) {
return false;
}
//获取Content-Type
String contentType = request.getContentType();
return (contentType != null) && (contentType.toLowerCase().startsWith("multipart/"));
}
}

View File

@@ -1,4 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hccake.ballcat.commom.log.operation.OperationLogAutoConfiguration,\
com.hccake.ballcat.commom.log.access.AccessLogAutoConfiguration,\
com.hccake.ballcat.commom.log.error.ErrorLogAutoConfiguration

View File

@@ -0,0 +1,25 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ballcat-common</artifactId>
<groupId>com.hccake</groupId>
<version>0.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ballcat-common-storage</artifactId>
<dependencies>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,32 @@
package com.hccake.ballcat.commom.storage;
import com.hccake.ballcat.commom.storage.aliyun.AliyunOssClient;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* oss 自动配置类
* @author Hccake
*/
@AllArgsConstructor
@EnableConfigurationProperties({FileStorageProperties.class})
public class FileStorageAutoConfiguration {
private final FileStorageProperties properties;
@Bean
@ConditionalOnMissingBean(FileStorageClient.class)
@ConditionalOnProperty(name = "file.storage.type", havingValue = "aliyun")
FileStorageClient aliyunOssClient() {
return new AliyunOssClient(
properties.getEndpoint(),
properties.getAccessKey(),
properties.getAccessSecret(),
properties.getBucketName()
);
}
}

View File

@@ -0,0 +1,27 @@
package com.hccake.ballcat.commom.storage;
import java.io.InputStream;
/**
* @author Hccake
* @version 1.0
* @date 2020/1/7 16:28
*/
public interface FileStorageClient {
/**
* 文件上传
* @param objectName 存储对象名称
* @param inputStream 文件输入流
* @return 文件相对路径
*/
String putObject(String objectName, InputStream inputStream);
/**
* 文件删除
* @param objectName 存储对象名称
*/
void deleteObject(String objectName);
}

View File

@@ -0,0 +1,34 @@
package com.hccake.ballcat.commom.storage;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author Hccake
* @version 1.0
* @date 2019/7/16 15:34
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "file.storage")
public class FileStorageProperties {
/**
* endpoint 服务地址 http://oss-cn-qingdao.aliyuncs.com
*/
private String endpoint;
/**
* 密钥key
*/
private String accessKey;
/**
* 密钥Secret
*/
private String accessSecret;
/**
* bucketName
*/
private String bucketName;
}

View File

@@ -0,0 +1,69 @@
package com.hccake.ballcat.commom.storage.aliyun;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.hccake.ballcat.commom.storage.FileStorageClient;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import java.io.InputStream;
/**
* @author Hccake
* @version 1.0
* @date 2019/7/16 15:45
*/
@RequiredArgsConstructor
public class AliyunOssClient implements FileStorageClient, InitializingBean, DisposableBean {
private final String endpoint;
private final String accessKey;
private final String accessSecret;
private final String bucketName;
private OSS client;
/**
* 文件上传
*
* @param objectName 存储对象名称
* @param inputStream 文件输入流
* @return
*/
@Override
public String putObject(String objectName, InputStream inputStream) {
client.putObject(bucketName, objectName, inputStream);
return objectName;
}
/**
* 文件删除
* @param objectName 存储对象名称
*/
@Override
public void deleteObject(String objectName){
if (client.doesObjectExist(bucketName, objectName)) {
client.deleteObject(bucketName, objectName);
}
}
@Override
public void afterPropertiesSet() {
Assert.hasText(endpoint, "endpoint 为空");
Assert.hasText(accessKey, "Oss accessKey为空");
Assert.hasText(accessSecret, "Oss accessSecret为空");
client = new OSSClientBuilder().build(endpoint, accessKey, accessSecret);
}
@Override
public void destroy() {
if (this.client != null) {
this.client.shutdown();
}
}
}

View File

@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hccake.ballcat.commom.storage.FileStorageAutoConfiguration

View File

@@ -20,6 +20,7 @@
<module>ballcat-common-conf</module>
<module>ballcat-common-job</module>
<module>ballcat-common-swagger</module>
<module>ballcat-common-storage</module>
</modules>