Initial commit
Made-with: Cursor
This commit is contained in:
2
astral-service/astral-common/.gitattributes
vendored
Normal file
2
astral-service/astral-common/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/mvnw text eol=lf
|
||||
*.cmd text eol=crlf
|
||||
33
astral-service/astral-common/.gitignore
vendored
Normal file
33
astral-service/astral-common/.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
77
astral-service/astral-common/pom.xml
Normal file
77
astral-service/astral-common/pom.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?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>
|
||||
<groupId>com.astral</groupId>
|
||||
<artifactId>astral-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>astral-common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<!-- Java 9+ no longer bundles javax.activation; required by MimeTypeUtil -->
|
||||
<dependency>
|
||||
<groupId>com.sun.activation</groupId>
|
||||
<artifactId>javax.activation</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.upyun</groupId>
|
||||
<artifactId>java-sdk</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.12.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.17.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.astral.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 树节点
|
||||
*/
|
||||
@Data
|
||||
public class TreeNode {
|
||||
|
||||
private String id;
|
||||
|
||||
private String key;
|
||||
|
||||
private String pkey;
|
||||
|
||||
private String label;
|
||||
|
||||
private Integer sortNum;
|
||||
|
||||
private String type;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<TreeNode> children = new ArrayList<>();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.astral.common.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "astral")
|
||||
public class AstralConfig {
|
||||
|
||||
private static String uploadType;
|
||||
|
||||
private static String uploadDir;
|
||||
|
||||
public static String getUploadType() {
|
||||
return uploadType;
|
||||
}
|
||||
|
||||
public void setUploadType(String uploadType) {
|
||||
AstralConfig.uploadType = uploadType;
|
||||
}
|
||||
|
||||
public static String getUploadDir() {
|
||||
return uploadDir;
|
||||
}
|
||||
|
||||
public void setUploadDir(String uploadDir) {
|
||||
AstralConfig.uploadDir = uploadDir;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.astral.common.config;
|
||||
|
||||
import com.astral.common.utils.UpYunUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class UpyunConfig {
|
||||
|
||||
@Value("${upyun.bucket}")
|
||||
private String bucket;
|
||||
|
||||
@Value("${upyun.operator}")
|
||||
private String operator;
|
||||
|
||||
@Value("${upyun.password}")
|
||||
private String password;
|
||||
|
||||
@Value("${upyun.domain}")
|
||||
private String domain;
|
||||
|
||||
@Bean
|
||||
public void initUpyun(){
|
||||
UpYunUtil.setBucket(bucket);
|
||||
UpYunUtil.setOperator(operator);
|
||||
UpYunUtil.setPassword(password);
|
||||
UpYunUtil.setDomain(domain);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.astral.common.constant;
|
||||
|
||||
/**
|
||||
* 业务枚举
|
||||
*/
|
||||
public class BusinessEmnu {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.astral.common.constant;
|
||||
|
||||
public class CommonConstant {
|
||||
|
||||
public static final Integer SC_OK_200 = 200;
|
||||
|
||||
public static final Integer SC_ERROR_500 = 500;
|
||||
|
||||
public static final Integer SC_ERROR_401 = 401;
|
||||
|
||||
/**
|
||||
* 无权限访问返回码
|
||||
*/
|
||||
public static final Integer SC_JEECG_NO_AUTHZ = 510;
|
||||
|
||||
/**
|
||||
* 文件上传类型(本地:local,upyun,minio)
|
||||
*/
|
||||
public static final String UPLOAD_TYPE_LOCAL = "local";
|
||||
public static final String UPLOAD_TYPE_UPYUN = "upyun";
|
||||
public static final String UPLOAD_TYPE_MINIO = "minio";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
package com.astral.common.controller;
|
||||
|
||||
import com.astral.common.config.AstralConfig;
|
||||
import com.astral.common.config.UpyunConfig;
|
||||
import com.astral.common.constant.CommonConstant;
|
||||
import com.astral.common.result.Result;
|
||||
import com.astral.common.utils.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/common")
|
||||
public class CommonController {
|
||||
|
||||
@GetMapping("/download")
|
||||
public void download(String fileUrl, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
try {
|
||||
if (!FileUtils.checkAllowDownload(fileUrl)) {
|
||||
throw new RuntimeException("资源文件(" + fileUrl + ")非法,不允许下载。 ");
|
||||
}
|
||||
// 本地资源路径
|
||||
String localPath = AstralConfig.getUploadDir();
|
||||
// 数据库资源地址
|
||||
String downloadPath = localPath + "/" + fileUrl;
|
||||
// 下载名称
|
||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||
// downloadName = URLDecoder.decode(downloadName, "UTF-8");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, downloadName);
|
||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(value = "/static/**")
|
||||
public void getFile(HttpServletRequest request, HttpServletResponse response) {
|
||||
String imgPath = extractPathFromPattern(request);
|
||||
if(StringUtils.isBlank(imgPath) || "null".equals(imgPath)){
|
||||
return;
|
||||
}
|
||||
if (CommonConstant.UPLOAD_TYPE_UPYUN.equals(AstralConfig.getUploadType())) {
|
||||
String url = UpYunUtil.getDomain() + "/" + imgPath;
|
||||
try {
|
||||
response.sendRedirect(url);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
InputStream inputStream = null;
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
imgPath = imgPath.replace("..", "").replace("../","");
|
||||
if (imgPath.endsWith(",")) {
|
||||
imgPath = imgPath.substring(0, imgPath.length() - 1);
|
||||
}
|
||||
String filePath = AstralConfig.getUploadDir() + "/" + imgPath;
|
||||
// 先将加号替换为URL编码形式,避免被转为空格
|
||||
filePath = filePath.replaceAll("\\+", "%2B");
|
||||
filePath = URLDecoder.decode(filePath, "UTF-8");
|
||||
File file = new File(filePath);
|
||||
if(!file.exists()){
|
||||
// Missing resource should be a normal 404, not a server error (500).
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取文件扩展名
|
||||
String fileName = file.getName();
|
||||
String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||
|
||||
// 自动获取MIME类型
|
||||
String mimeType = MimeTypeUtil.getContentType(fileName);
|
||||
response.setContentType(mimeType);
|
||||
|
||||
// 根据文件类型确定处理方式
|
||||
if (shouldDisplayInline(extension)) {
|
||||
// 可预览文件 - 内联显示
|
||||
response.setHeader("Content-Disposition", "inline; filename=\"" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1") + "\"");
|
||||
} else {
|
||||
// 不可预览文件 - 下载
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1") + "\"");
|
||||
}
|
||||
// response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
|
||||
// 强制缓存
|
||||
response.setHeader("Cache-Control", "max-age=31536000");
|
||||
|
||||
inputStream = new BufferedInputStream(new FileInputStream(filePath));
|
||||
outputStream = response.getOutputStream();
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = inputStream.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0, len);
|
||||
}
|
||||
response.flushBuffer();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
response.setStatus(404);
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否可内联显示
|
||||
private boolean shouldDisplayInline(String extension) {
|
||||
switch (extension) {
|
||||
// 图片格式
|
||||
case "jpg": case "jpeg": case "png":
|
||||
case "gif": case "bmp": case "svg":
|
||||
// 文本格式
|
||||
case "txt": case "csv":
|
||||
// 网页格式
|
||||
case "html": case "htm":
|
||||
return true;
|
||||
// 默认不可内联显示
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static String extractPathFromPattern(final HttpServletRequest request) {
|
||||
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
|
||||
}
|
||||
|
||||
@PostMapping("/upload")
|
||||
public Result<?> uploadFile(HttpServletRequest request, MultipartFile file) throws Exception {
|
||||
try {
|
||||
String bizPath = request.getParameter("biz");
|
||||
String type = request.getParameter("type");
|
||||
|
||||
// 是否为文件名添加时间戳后缀
|
||||
boolean needTimestampSuffix = !(bizPath != null && bizPath.contains("upload/3DEditor"));
|
||||
if ("Tiles".equals(type)) {
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
int subIndex = originalFilename.lastIndexOf(".");
|
||||
String fileExtension = originalFilename.substring(subIndex);
|
||||
if (".zip".equals(fileExtension)) {
|
||||
String zipDirectory = originalFilename.substring(0, subIndex) + "-" + System.currentTimeMillis();
|
||||
if (StringUtils.isNotBlank(bizPath)) {
|
||||
zipDirectory = bizPath + "/" + zipDirectory;
|
||||
}
|
||||
String targetDirectory = AstralConfig.getUploadDir() + "/" + zipDirectory;
|
||||
boolean flag = ZipUtil.extractZipCheckFile(file, targetDirectory, "tileset.json");
|
||||
if (!flag) {
|
||||
CommonUtils.deleteFile(zipDirectory);
|
||||
throw new RuntimeException("文件异常,请检查上传的zip文件是否包含tileset.json文件");
|
||||
}
|
||||
return Result.success("上传成功", zipDirectory);
|
||||
} else {
|
||||
String fileName = CommonUtils.upload(bizPath, file, needTimestampSuffix);
|
||||
return Result.success("上传成功",fileName);
|
||||
}
|
||||
} else {
|
||||
// 上传并返回新文件名称
|
||||
String fileName = CommonUtils.upload(bizPath, file, needTimestampSuffix);
|
||||
return Result.success("上传成功",fileName);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/deleteFile")
|
||||
public Result<?> deleteFile(String fileUrl) {
|
||||
return Result.toAjax(CommonUtils.deleteFile(fileUrl));
|
||||
}
|
||||
|
||||
@PostMapping("/zipUploadExtraction")
|
||||
public Result<?> zipUploadExtraction(HttpServletRequest request, MultipartFile file) throws Exception {
|
||||
try {
|
||||
String bizPath = request.getParameter("biz");
|
||||
// 上传并返回新文件名称
|
||||
ZipUtil.extractZip(file, bizPath);
|
||||
return Result.success("上传成功");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.astral.common.result;
|
||||
|
||||
import com.astral.common.constant.CommonConstant;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6098323041897792633L;
|
||||
|
||||
private Integer code;
|
||||
private boolean success;
|
||||
private String message;
|
||||
private T result;
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
public Result(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static<T> Result<T> success() {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> success(String message) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(true);
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> success(T data) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(true);
|
||||
result.setResult(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> success(Boolean flag) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(flag);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> success(String message, T data) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(true);
|
||||
result.setMessage(message);
|
||||
result.setResult(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> error(String message) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_ERROR_500);
|
||||
result.setSuccess(false);
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> error(Integer code, String message) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(code);
|
||||
result.setSuccess(false);
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> error(String message, T data) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_ERROR_500);
|
||||
result.setSuccess(false);
|
||||
result.setMessage(message);
|
||||
result.setResult(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> error401(String message) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_ERROR_401);
|
||||
result.setSuccess(false);
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> error401(String message, T data) {
|
||||
Result<T> result = new Result<T>();
|
||||
result.setCode(CommonConstant.SC_ERROR_401);
|
||||
result.setSuccess(false);
|
||||
result.setMessage(message);
|
||||
result.setResult(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无权限访问返回结果
|
||||
*/
|
||||
public static<T> Result<T> noauth(String msg) {
|
||||
return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg);
|
||||
}
|
||||
|
||||
public static<T> Result<T> toAjax(Boolean flag) {
|
||||
Result<T> result = new Result<T>();
|
||||
if (flag) {
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(true);
|
||||
} else {
|
||||
result.setCode(CommonConstant.SC_ERROR_500);
|
||||
result.setSuccess(false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static<T> Result<T> toAjax(int row) {
|
||||
Result<T> result = new Result<T>();
|
||||
if (row > 0) {
|
||||
result.setCode(CommonConstant.SC_OK_200);
|
||||
result.setSuccess(true);
|
||||
} else {
|
||||
result.setCode(CommonConstant.SC_ERROR_500);
|
||||
result.setSuccess(false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import com.astral.common.config.AstralConfig;
|
||||
import com.astral.common.constant.CommonConstant;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CommonUtils {
|
||||
|
||||
private static String defaultUploadType = AstralConfig.getUploadType();
|
||||
|
||||
// 重载方法,保持原签名(默认需要时间戳后缀)
|
||||
public static String upload(String bizPath, MultipartFile file) {
|
||||
return upload(bizPath, file, true);
|
||||
}
|
||||
|
||||
public static String upload(String bizPath, MultipartFile file, boolean needTimestampSuffix) {
|
||||
String result = "";
|
||||
try {
|
||||
if (CommonConstant.UPLOAD_TYPE_UPYUN.equals(defaultUploadType)) {
|
||||
result = UpYunUtil.upload(bizPath, FileUtils.convertFile(file,needTimestampSuffix));
|
||||
} else {
|
||||
result = FileUploadUtils.upload(bizPath, file,needTimestampSuffix);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String upload(String bizPath, File file) {
|
||||
return upload(bizPath, file, true);
|
||||
}
|
||||
|
||||
public static String upload(String bizPath, File file, boolean needTimestampSuffix) {
|
||||
String result = "";
|
||||
try {
|
||||
if (CommonConstant.UPLOAD_TYPE_UPYUN.equals(defaultUploadType)) {
|
||||
result = UpYunUtil.upload(bizPath, file);
|
||||
} else {
|
||||
result = FileUploadUtils.upload(bizPath, file, needTimestampSuffix);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用文件删除(慎用)
|
||||
* @param dirPath
|
||||
* @return
|
||||
*/
|
||||
public static Boolean deleteFile(String dirPath) {
|
||||
if (StringUtils.isBlank(dirPath)) {
|
||||
return false;
|
||||
}
|
||||
dirPath = AstralConfig.getUploadDir() + "/" + dirPath;
|
||||
try {
|
||||
if (CommonConstant.UPLOAD_TYPE_UPYUN.equals(defaultUploadType)) {
|
||||
return UpYunUtil.deleteFile(dirPath);
|
||||
} else {
|
||||
File file = new File(dirPath);
|
||||
org.apache.commons.io.FileUtils.forceDelete(file);
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("文件删除失败:" + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否是json字符串
|
||||
*/
|
||||
public static Boolean isJsonValid(String jsonStr) {
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.readTree(jsonStr);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import com.astral.common.config.AstralConfig;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 文件上传工具类
|
||||
*/
|
||||
public class FileUploadUtils {
|
||||
|
||||
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
|
||||
|
||||
public static final long DEFAULT_MAX_SIZE = 10L * 1024 * 1024 * 1024;
|
||||
|
||||
private static String defaultBaseDir = AstralConfig.getUploadDir();
|
||||
|
||||
public static String getDefaultBaseDir() {
|
||||
return defaultBaseDir;
|
||||
}
|
||||
|
||||
public static final String upload(String baseDir, MultipartFile file) throws IOException{
|
||||
return upload(baseDir, file,true);
|
||||
}
|
||||
|
||||
public static final String upload(String baseDir, MultipartFile file, boolean needTimestampSuffix) throws IOException{
|
||||
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
|
||||
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
|
||||
throw new RuntimeException("文件名长度超过限制");
|
||||
}
|
||||
|
||||
String fileName = "";
|
||||
if(needTimestampSuffix){
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
int subIndex = originalFilename.lastIndexOf(".");
|
||||
String fileExtension = originalFilename.substring(subIndex);
|
||||
fileName = originalFilename.substring(0, subIndex) + "_" + System.currentTimeMillis() + fileExtension;
|
||||
}else{
|
||||
fileName = file.getOriginalFilename();
|
||||
}
|
||||
|
||||
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
|
||||
file.transferTo(Paths.get(absPath));
|
||||
return getPathFileName(baseDir, fileName);
|
||||
}
|
||||
|
||||
public static final String upload(String baseDir, File file) throws IOException{
|
||||
return upload(baseDir, file,true);
|
||||
}
|
||||
|
||||
public static final String upload(String baseDir, File file, boolean needTimestampSuffix) throws IOException {
|
||||
int fileNamelength = Objects.requireNonNull(file.getName()).length();
|
||||
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
|
||||
throw new RuntimeException("文件名长度超过限制");
|
||||
}
|
||||
|
||||
String fileName = "";
|
||||
if(needTimestampSuffix){
|
||||
String originalFilename = file.getName();
|
||||
int subIndex = originalFilename.lastIndexOf(".");
|
||||
String fileExtension = originalFilename.substring(subIndex);
|
||||
fileName = originalFilename.substring(0, subIndex) + "_" + System.currentTimeMillis() + fileExtension;
|
||||
}else{
|
||||
fileName = file.getName();
|
||||
}
|
||||
|
||||
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
|
||||
Files.copy(file.toPath(), Paths.get(absPath), StandardCopyOption.REPLACE_EXISTING);
|
||||
return getPathFileName(baseDir, fileName);
|
||||
}
|
||||
|
||||
public static final File getAbsoluteFile(String uploadDir, String fileName) {
|
||||
File desc = new File(defaultBaseDir + "/" + getPathFileName(uploadDir, fileName));
|
||||
if (!desc.exists()) {
|
||||
if (!desc.getParentFile().exists()) {
|
||||
desc.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static final String getPathFileName(String uploadDir, String fileName) {
|
||||
if (StringUtils.hasLength(uploadDir)) {
|
||||
return uploadDir + "/" + fileName;
|
||||
} else {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
|
||||
public class FileUtils {
|
||||
public static File convertFile(MultipartFile file) throws IOException {
|
||||
return convertFile(file,true);
|
||||
}
|
||||
|
||||
public static File convertFile(MultipartFile file, boolean needTimestampSuffix) throws IOException {
|
||||
String fileName = "";
|
||||
|
||||
if(needTimestampSuffix){
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
int subIndex = originalFilename.lastIndexOf(".");
|
||||
String fileExtension = originalFilename.substring(subIndex);
|
||||
fileName = originalFilename.substring(0, subIndex) + "_" + System.currentTimeMillis() + fileExtension;
|
||||
}else{
|
||||
fileName = file.getOriginalFilename();
|
||||
}
|
||||
|
||||
File convFile = new File(fileName);
|
||||
convFile.createNewFile();
|
||||
try (FileOutputStream fos = new FileOutputStream(convFile)) {
|
||||
fos.write(file.getBytes());
|
||||
}
|
||||
return convFile;
|
||||
}
|
||||
|
||||
public static boolean checkAllowDownload(String resource) {
|
||||
// 禁止目录上跳级别
|
||||
if (StringUtils.contains(resource, "..")) {
|
||||
return false;
|
||||
}
|
||||
// todo 检查允许下载的文件规则
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
|
||||
String percentEncodedFileName = percentEncode(realFileName);
|
||||
|
||||
StringBuilder contentDispositionValue = new StringBuilder();
|
||||
contentDispositionValue.append("attachment; filename=")
|
||||
.append(percentEncodedFileName)
|
||||
.append(";")
|
||||
.append("filename*=")
|
||||
.append("utf-8''")
|
||||
.append(percentEncodedFileName);
|
||||
|
||||
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
|
||||
response.setHeader("Content-disposition", contentDispositionValue.toString());
|
||||
response.setHeader("download-filename", percentEncodedFileName);
|
||||
}
|
||||
|
||||
public static String percentEncode(String s) throws UnsupportedEncodingException {
|
||||
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
|
||||
return encode.replaceAll("\\+", "%20");
|
||||
}
|
||||
|
||||
public static void writeBytes(String filePath, OutputStream os) throws IOException {
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException(filePath);
|
||||
}
|
||||
fis = new FileInputStream(file);
|
||||
byte[] b = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(b)) > 0) {
|
||||
os.write(b, 0, length);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} finally {
|
||||
IOUtils.close(os);
|
||||
IOUtils.close(fis);
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteFolder(String folderPath) throws IOException {
|
||||
Path path = Paths.get(folderPath);
|
||||
if (Files.exists(path)) {
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
if (exc == null) {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
} else {
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JwtUtil {
|
||||
|
||||
private static final String SECRET_KEY = "JWT-Secret-Key";
|
||||
private static final int DEFAULT_EXPIRE_SECONDS = 120 * 60;
|
||||
private static final int PASSWORD_HASH_BYTES = 16;
|
||||
|
||||
private static final SecretKey key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
|
||||
|
||||
public static String generateToken(String userName, Long userId, int expiredSeconds) {
|
||||
if (expiredSeconds == 0) {
|
||||
expiredSeconds = DEFAULT_EXPIRE_SECONDS;
|
||||
}
|
||||
|
||||
Date expireAt = Date.from(Instant.now().plusSeconds(expiredSeconds));
|
||||
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("UserID", userId);
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setIssuer(userName)
|
||||
.setIssuedAt(new Date())
|
||||
.setExpiration(expireAt)
|
||||
.signWith(key, SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public static JwtPayload validateToken(String tokenString) {
|
||||
try {
|
||||
Jws<Claims> claimsJws = Jwts.parser()
|
||||
.setSigningKey(key)
|
||||
.build()
|
||||
.parseClaimsJws(tokenString);
|
||||
|
||||
Claims claims = claimsJws.getBody();
|
||||
|
||||
return new JwtPayload(
|
||||
claims.getIssuer(),
|
||||
((Number) claims.get("UserID")).intValue(),
|
||||
claims.getIssuedAt().getTime(),
|
||||
claims.getExpiration().getTime()
|
||||
);
|
||||
} catch (JwtException e) {
|
||||
throw new RuntimeException("Error: Unable to validate token");
|
||||
}
|
||||
}
|
||||
|
||||
public static String refreshToken(String tokenString) {
|
||||
try {
|
||||
Claims claims = Jwts.parser()
|
||||
.setSigningKey(key)
|
||||
.build()
|
||||
.parseClaimsJws(tokenString)
|
||||
.getBody();
|
||||
|
||||
Date expireAt = Date.from(Instant.now().plusSeconds(DEFAULT_EXPIRE_SECONDS));
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(new Date())
|
||||
.setExpiration(expireAt)
|
||||
.signWith(key, SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
} catch (JwtException e) {
|
||||
throw new RuntimeException("Error: Failed to generate new fresh JWT");
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateSalt() {
|
||||
byte[] buf = new byte[PASSWORD_HASH_BYTES];
|
||||
new SecureRandom().nextBytes(buf);
|
||||
return Hex.encodeHexString(buf);
|
||||
}
|
||||
|
||||
public static String generatePassHash(String password, String salt) {
|
||||
try {
|
||||
return Hex.encodeHexString(
|
||||
javax.crypto.SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
|
||||
.generateSecret(new javax.crypto.spec.PBEKeySpec(
|
||||
password.toCharArray(),
|
||||
salt.getBytes(),
|
||||
16384,
|
||||
PASSWORD_HASH_BYTES * 8))
|
||||
.getEncoded()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error: failed to generate password hash");
|
||||
}
|
||||
}
|
||||
|
||||
public static TokenStatus checkStatus(String tokenString) {
|
||||
try {
|
||||
JwtPayload jp = validateToken(tokenString);
|
||||
|
||||
long timeDiff = (jp.getExpiresAt() - System.currentTimeMillis()) / 1000;
|
||||
|
||||
if (timeDiff <= 30) {
|
||||
String newToken = refreshToken(tokenString);
|
||||
return new TokenStatus(newToken, timeDiff);
|
||||
}
|
||||
|
||||
return new TokenStatus(tokenString, timeDiff);
|
||||
} catch (Exception e) {
|
||||
return new TokenStatus("", -1L);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TokenStatus {
|
||||
private final String token;
|
||||
private final long timeDiff;
|
||||
|
||||
public TokenStatus(String token, long timeDiff) {
|
||||
this.token = token;
|
||||
this.timeDiff = timeDiff;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public long getTimeDiff() {
|
||||
return timeDiff;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JwtPayload {
|
||||
private final String username;
|
||||
private final int userId;
|
||||
private final long issuedAt;
|
||||
private final long expiresAt;
|
||||
|
||||
public JwtPayload(String username, int userId, long issuedAt, long expiresAt) {
|
||||
this.username = username;
|
||||
this.userId = userId;
|
||||
this.issuedAt = issuedAt;
|
||||
this.expiresAt = expiresAt;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public long getIssuedAt() {
|
||||
return issuedAt;
|
||||
}
|
||||
|
||||
public long getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class MimeTypeUtil {
|
||||
private static final MimetypesFileTypeMap MIME_TYPES;
|
||||
|
||||
static {
|
||||
try (InputStream is = MimeTypeUtil.class.getResourceAsStream("/mime.types")) {
|
||||
MIME_TYPES = new MimetypesFileTypeMap(is);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to load mime.types", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getContentType(String fileName) {
|
||||
return MIME_TYPES.getContentType(fileName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import com.astral.common.base.TreeNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 树构造工具类
|
||||
* @Author yx
|
||||
*/
|
||||
public class TreeBuilderUtil {
|
||||
|
||||
// /**
|
||||
// * 构建树形结构
|
||||
// * @param nodes 所有节点列表
|
||||
// * @return 树形结构列表
|
||||
// */
|
||||
// public static <T extends TreeNode<T>> List<T> buildTree(List<T> nodes) {
|
||||
// // 获取所有根节点
|
||||
// List<T> rootNodes = nodes.stream()
|
||||
// .filter(node -> StringUtils.isBlank(node.getPkey()))
|
||||
// .sorted(Comparator.comparingInt(T::getSortNum))
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// // 为每个根节点构建子树
|
||||
// for (T rootNode : rootNodes) {
|
||||
// buildChildNodes(rootNode, nodes);
|
||||
// }
|
||||
//
|
||||
// return rootNodes;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 递归构建子节点
|
||||
// * @param parentNode 父节点
|
||||
// * @param nodes 所有节点列表
|
||||
// */
|
||||
// private static <T extends TreeNode<T>> void buildChildNodes(T parentNode, List<T> nodes) {
|
||||
// // 获取当前节点的所有子节点
|
||||
// List<T> children = nodes.stream()
|
||||
// .filter(node -> parentNode.getKey().equals(node.getPkey()))
|
||||
// .sorted(Comparator.comparingInt(T::getSortNum))
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// // 递归构建每个子节点的子节点
|
||||
// for (T child : children) {
|
||||
// buildChildNodes(child, nodes);
|
||||
// }
|
||||
//
|
||||
// // 设置子节点列表
|
||||
// parentNode.setChildren(children);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 构建树形结构
|
||||
// * @param nodes 所有节点列表
|
||||
// * @return 树形结构列表
|
||||
// */
|
||||
// public static <T extends TreeNode<T>> List<TreeNode> build(List<T> nodes) {
|
||||
// // 按父节点ID分组
|
||||
// Map<String, List<T>> pCodeMap = nodes.stream()
|
||||
// .filter(node -> StringUtils.isNotBlank(node.getPkey()))
|
||||
// .collect(Collectors.groupingBy(T::getPkey));
|
||||
//
|
||||
// // 设置子节点
|
||||
// nodes.forEach(node -> {
|
||||
// List<T> children = pCodeMap.get(node.getKey());
|
||||
// if (children != null && !children.isEmpty()) {
|
||||
// // 排序(如果有sort字段)
|
||||
// children.sort(Comparator.comparingInt(T::getSortNum));
|
||||
// node.setChildren(children);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // 获取所有根节点
|
||||
// return nodes.stream()
|
||||
// .filter(node -> StringUtils.isBlank(node.getPkey()))
|
||||
// .sorted(Comparator.comparingInt(T::getSortNum))
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
|
||||
public static List<TreeNode> buildTree(List<TreeNode> nodes) {
|
||||
// 按父节点ID分组
|
||||
Map<String, List<TreeNode>> pCodeMap = nodes.stream()
|
||||
.filter(node -> StringUtils.isNotBlank(node.getPkey()))
|
||||
.collect(Collectors.groupingBy(treeNode -> treeNode.getPkey() + "_" + treeNode.getType()));
|
||||
|
||||
// 设置子节点
|
||||
nodes.forEach(node -> {
|
||||
List<TreeNode> children = pCodeMap.get(node.getKey() + "_" + node.getType());
|
||||
if (children != null && !children.isEmpty()) {
|
||||
// 排序(如果有sort字段)
|
||||
children.sort(Comparator.comparing(TreeNode::getSortNum, Comparator.nullsLast(Comparator.naturalOrder())));
|
||||
node.setChildren(children);
|
||||
}
|
||||
});
|
||||
|
||||
// 获取所有根节点
|
||||
return nodes.stream()
|
||||
.filter(node -> StringUtils.isBlank(node.getPkey()))
|
||||
.sorted(Comparator.comparing(TreeNode::getSortNum, Comparator.nullsLast(Comparator.naturalOrder())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import com.UpYun;
|
||||
import com.astral.common.config.AstralConfig;
|
||||
import com.upyun.FormUploader;
|
||||
import com.upyun.Params;
|
||||
import com.upyun.Result;
|
||||
import com.upyun.UpException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UpYunUtil {
|
||||
|
||||
private static String bucket;
|
||||
|
||||
private static String operator;
|
||||
|
||||
private static String password;
|
||||
|
||||
private static String domain;
|
||||
|
||||
public static void setBucket(String bucket) {
|
||||
UpYunUtil.bucket = bucket;
|
||||
}
|
||||
|
||||
public static String getBucket() {
|
||||
return bucket;
|
||||
}
|
||||
|
||||
public static void setOperator(String operator) {
|
||||
UpYunUtil.operator = operator;
|
||||
}
|
||||
|
||||
public static String getOperator() {
|
||||
return operator;
|
||||
}
|
||||
|
||||
public static void setPassword(String password) {
|
||||
UpYunUtil.password = password;
|
||||
}
|
||||
|
||||
public static String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public static String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public static void setDomain(String domain) {
|
||||
UpYunUtil.domain = domain;
|
||||
}
|
||||
|
||||
public static String upload(String savePath, File file) {
|
||||
|
||||
// 创建FormUploader实例
|
||||
FormUploader uploader = new FormUploader(bucket, operator, password);
|
||||
|
||||
// 设置上传参数
|
||||
Map<String, Object> paramsMap = new HashMap<>();
|
||||
String uploadDir = AstralConfig.getUploadDir();
|
||||
if (StringUtils.hasLength(uploadDir)) {
|
||||
savePath = uploadDir + "/" + savePath;
|
||||
}
|
||||
paramsMap.put(Params.SAVE_KEY, savePath);
|
||||
|
||||
try {
|
||||
// 执行上传
|
||||
Result result = uploader.upload(paramsMap, file);
|
||||
// 处理上传结果
|
||||
if (result.isSucceed()) {
|
||||
System.out.println("文件上传成功!");
|
||||
} else {
|
||||
System.out.println("文件上传失败!");
|
||||
System.out.println("错误信息: " + result.getMsg());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("文件上传失败->" + e.getMessage());
|
||||
}
|
||||
return savePath;
|
||||
}
|
||||
|
||||
public static boolean deleteFile(String dirPath) throws IOException, UpException {
|
||||
UpYun upyun = new UpYun(bucket, operator, password);
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put(UpYun.PARAMS.KEY_X_LIST_LIMIT.getValue(), "100");
|
||||
List<UpYun.FolderItem> folderItems = new ArrayList<>();
|
||||
do {
|
||||
folderItems = upyun.readDir(dirPath, params);
|
||||
if (!CollectionUtils.isEmpty(folderItems)) {
|
||||
folderItems.forEach(item -> {
|
||||
try {
|
||||
if ("folder".equals(item.type) || "Folder".equals(item.type)) {
|
||||
deleteFile(dirPath + "/" + item.name);
|
||||
} else {
|
||||
upyun.deleteFile(dirPath + "/" + item.name, null);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UpException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} while (!CollectionUtils.isEmpty(folderItems));
|
||||
return upyun.rmDir(dirPath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.astral.common.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class ZipUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ZipUtil.class);
|
||||
|
||||
/**
|
||||
* 解压ZIP文件到指定目录
|
||||
*/
|
||||
public static void extractZip(MultipartFile zipFile, String targetDirectory) throws IOException {
|
||||
// 创建目标目录
|
||||
File targetDir = new File(targetDirectory);
|
||||
if (!targetDir.exists()) {
|
||||
targetDir.mkdirs();
|
||||
}
|
||||
try {
|
||||
ZipInputStream zipInputStream = new ZipInputStream(zipFile.getInputStream());
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
if (!entry.isDirectory()) {
|
||||
File extractedFile = extractFile(zipInputStream, targetDir, entry.getName());
|
||||
}
|
||||
zipInputStream.closeEntry();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean extractZipCheckFile(MultipartFile zipFile, String targetDirectory, String checkFileName) throws IOException {
|
||||
// 创建目标目录
|
||||
File targetDir = new File(targetDirectory);
|
||||
if (!targetDir.exists()) {
|
||||
targetDir.mkdirs();
|
||||
}
|
||||
boolean flag = false;
|
||||
try {
|
||||
ZipInputStream zipInputStream = new ZipInputStream(zipFile.getInputStream());
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
if (!entry.isDirectory()) {
|
||||
File extractedFile = extractFile(zipInputStream, targetDir, entry.getName());
|
||||
System.out.println(entry.getName());
|
||||
if (checkFileName.equals(entry.getName())) {
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
zipInputStream.closeEntry();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
private static File extractFile(ZipInputStream zipInputStream, File targetDir, String fileName) throws IOException {
|
||||
File file = new File(targetDir, fileName);
|
||||
|
||||
// 创建父目录
|
||||
File parent = file.getParentFile();
|
||||
if (!parent.exists()) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(file);
|
||||
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = zipInputStream.read(buffer)) > 0) {
|
||||
bos.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user