feat:文件上传的功能开发
parent
56edda8b97
commit
078f324494
@ -0,0 +1,17 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "报文确认状态")
|
||||||
|
public class ConfirmationStatusResult {
|
||||||
|
@Schema(description = "报文确认状态", allowableValues = {"待确认", "已确认"})
|
||||||
|
private final String confirmationStatus;
|
||||||
|
|
||||||
|
public ConfirmationStatusResult(String confirmationStatus) {
|
||||||
|
this.confirmationStatus = confirmationStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfirmationStatus() {
|
||||||
|
return confirmationStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "面额拆解结果")
|
||||||
|
public class DenominationDecompositionResult {
|
||||||
|
private final Integer totalCount;
|
||||||
|
private final List<DenominationBreakdownResult> breakdown;
|
||||||
|
|
||||||
|
public DenominationDecompositionResult(Integer totalCount, List<DenominationBreakdownResult> breakdown) {
|
||||||
|
this.totalCount = totalCount;
|
||||||
|
this.breakdown = breakdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTotalCount() {
|
||||||
|
return totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DenominationBreakdownResult> getBreakdown() {
|
||||||
|
return breakdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "操作校验结果")
|
||||||
|
public class OperationBooleanResult {
|
||||||
|
@Schema(description = "本次校验是否通过")
|
||||||
|
private final boolean valid;
|
||||||
|
|
||||||
|
public OperationBooleanResult(boolean valid) {
|
||||||
|
this.valid = valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "创建或接收操作结果")
|
||||||
|
public class OperationIdStatusResult {
|
||||||
|
@Schema(description = "后续操作所需的业务记录编号")
|
||||||
|
private final Long verificationId;
|
||||||
|
@Schema(description = "本次操作完成后的状态")
|
||||||
|
private final String status;
|
||||||
|
|
||||||
|
public OperationIdStatusResult(Long id, String status) {
|
||||||
|
this.verificationId = id;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getVerificationId() {
|
||||||
|
return verificationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "操作生成的报文")
|
||||||
|
public class OperationMessageResult {
|
||||||
|
@Schema(description = "本次操作生成的报文")
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
public OperationMessageResult(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "操作状态")
|
||||||
|
public class OperationStatusResult {
|
||||||
|
@Schema(description = "本次操作完成后的状态")
|
||||||
|
private final String status;
|
||||||
|
|
||||||
|
public OperationStatusResult(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "操作生成值")
|
||||||
|
public class OperationValueResult {
|
||||||
|
@Schema(description = "本次操作生成的值")
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public OperationValueResult(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.yau.digitalrmb.institutionidentity.application;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "标准币串步骤操作结果")
|
||||||
|
public class StandardCurrencyOperationResult {
|
||||||
|
private final String status;
|
||||||
|
private final Integer totalCount;
|
||||||
|
|
||||||
|
public StandardCurrencyOperationResult(String status, Integer totalCount) {
|
||||||
|
this.status = status;
|
||||||
|
this.totalCount = totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTotalCount() {
|
||||||
|
return totalCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
package com.yau.digitalrmb.shared.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
@Component
|
||||||
|
public class LocalFileUtil implements IFileUtil{
|
||||||
|
|
||||||
|
private final static List<String> excludeSp = Arrays.asList("exe", "bin", "sh");
|
||||||
|
|
||||||
|
private final String localPath;
|
||||||
|
|
||||||
|
public LocalFileUtil(@Value("${file.path}")String localPath) {
|
||||||
|
this.localPath = localPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String upload(MultipartFile file) {
|
||||||
|
return upload(null, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String upload(String objectName, InputStream fileIn) {
|
||||||
|
Assert.notNull(fileIn, "文件不能为空");
|
||||||
|
Assert.hasText(objectName, "文件名为空");
|
||||||
|
Assert.isTrue(objectName.lastIndexOf(".") > 0, "文件名称需携带扩展后缀");
|
||||||
|
FileOutputStream out = null;
|
||||||
|
try {
|
||||||
|
String relativePath = getDiskRelativePath(objectName, null);
|
||||||
|
File file = new File(getFullPath(relativePath));
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
out = new FileOutputStream(file);
|
||||||
|
byte[] buff = new byte[4096];
|
||||||
|
int len;
|
||||||
|
while ((len = fileIn.read(buff)) != -1) {
|
||||||
|
out.write(buff, 0, len);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
return relativePath;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new IllegalArgumentException("上传文件失败,IO错误");
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
fileIn.close();
|
||||||
|
if (out != null) out.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(String path) {
|
||||||
|
if (!StringUtils.hasText(path)) return false;
|
||||||
|
File file = new File(getFullPath(path));
|
||||||
|
if (!file.exists()) return false;
|
||||||
|
return file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void download(HttpServletResponse response, String fileName, String relativePath) {
|
||||||
|
Assert.hasText(relativePath, "路径为空");
|
||||||
|
System.out.println("------------------------------------" + getFullPath(relativePath));
|
||||||
|
File file = new File(getFullPath(relativePath));
|
||||||
|
Assert.isTrue(file.exists(), "附件不存在");
|
||||||
|
String sp = relativePath.substring(relativePath.lastIndexOf(".") + 1);
|
||||||
|
Assert.isTrue(!excludeSp.contains(sp.toLowerCase()), "文件类型错误");
|
||||||
|
if (!StringUtils.hasText(fileName)) {
|
||||||
|
fileName = file.getName().substring(0, file.getName().lastIndexOf("."));
|
||||||
|
}
|
||||||
|
InputStream fis = null;
|
||||||
|
try {
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode((fileName + "." + sp), CharsetUtil.UTF_8));
|
||||||
|
fis = new BufferedInputStream(Files.newInputStream(file.toPath()));
|
||||||
|
response.addHeader("Content-Length", String.valueOf(fis.available()));
|
||||||
|
byte[] buff = new byte[4096];
|
||||||
|
int len;
|
||||||
|
while ((len = fis.read(buff)) != -1) {
|
||||||
|
response.getOutputStream().write(buff, 0, len);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("下载文件失败: " + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (fis != null) fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void download(HttpServletResponse response, String relativePath) {
|
||||||
|
download(response, null, relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFullPath(String relativePath) {
|
||||||
|
if (!relativePath.startsWith("/")) {
|
||||||
|
relativePath = "/" + relativePath;
|
||||||
|
}
|
||||||
|
return localPath + relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSuffix(String fileName) {
|
||||||
|
Assert.hasText(fileName, "文件名不存在!");
|
||||||
|
if (fileName.lastIndexOf(".") < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String upload(String fileName, MultipartFile file) {
|
||||||
|
return upload(fileName, file, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDiskRelativePath(String fileName, String suffix) {
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
Date d = new Date();
|
||||||
|
c.setTime(d);
|
||||||
|
String year = Integer.toString(c.get(Calendar.YEAR));
|
||||||
|
String month = Integer.toString(c.get(Calendar.MONTH) + 1);
|
||||||
|
String day = Integer.toString(c.get(Calendar.DATE));
|
||||||
|
StringBuilder path = new StringBuilder();
|
||||||
|
path.append("/").append(year)
|
||||||
|
.append("/").append(month)
|
||||||
|
.append("/").append(day)
|
||||||
|
.append("/").append(fileName);
|
||||||
|
if (StringUtils.hasText(suffix)) path.append(".").append(suffix);
|
||||||
|
return path.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String upload(String fileName, MultipartFile file, String relativePath) {
|
||||||
|
Assert.isTrue(!file.isEmpty(), "文件不存在");
|
||||||
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
if (fileName == null) fileName = IdUtil.simpleUUID();
|
||||||
|
String sp = getSuffix(originalFilename);
|
||||||
|
Assert.notNull(sp, "文件类型错误");
|
||||||
|
Assert.isTrue(!excludeSp.contains(sp.toLowerCase()), "文件类型错误");
|
||||||
|
try {
|
||||||
|
String filePath;
|
||||||
|
if (relativePath == null) {
|
||||||
|
filePath = getDiskRelativePath(fileName, sp);
|
||||||
|
} else {
|
||||||
|
relativePath = relativePath.endsWith("/") ? relativePath : relativePath + "/";
|
||||||
|
filePath = relativePath + fileName + "." + sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
File destFile = new File(getFullPath(filePath));
|
||||||
|
destFile.getParentFile().mkdirs();
|
||||||
|
file.transferTo(destFile);
|
||||||
|
return filePath;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new IllegalArgumentException("上传文件失败,FileNotFound错误");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalArgumentException("上传文件失败,IO错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package com.yau.digitalrmb.shared.config;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出参对象统一封装
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class ResultDataEntity<T> {
|
||||||
|
/**
|
||||||
|
* 状态码
|
||||||
|
*/
|
||||||
|
private final Integer code;
|
||||||
|
/**
|
||||||
|
* 异常提示
|
||||||
|
*/
|
||||||
|
// @JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private String msg = null;
|
||||||
|
/**
|
||||||
|
* 返回体对象
|
||||||
|
*/
|
||||||
|
// @JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private T data = null;
|
||||||
|
|
||||||
|
|
||||||
|
private Flux<String> flow;
|
||||||
|
|
||||||
|
public ResultDataEntity(T data) {
|
||||||
|
this.code = HttpStatus.OK.value();
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultDataEntity(HttpStatus status, T data) {
|
||||||
|
this.code = status.value();
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultDataEntity(HttpStatus status, Flux<String> data) {
|
||||||
|
this.code = status.value();
|
||||||
|
this.flow = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultDataEntity(HttpStatus status, String msg, T data) {
|
||||||
|
this.code = status.value();
|
||||||
|
this.msg = msg;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultDataEntity(String msg) {
|
||||||
|
this.code = HttpStatus.OK.value();
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultDataEntity(HttpStatus status, String msg) {
|
||||||
|
this.code = status.value();
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultDataEntity(HttpStatus status) {
|
||||||
|
this.code = status.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.yau.digitalrmb.shared.config;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对ResponseEntity做了简单包装
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ApiModel("API返回对象")
|
||||||
|
@Getter
|
||||||
|
public class ResultEntity<T> extends ResponseEntity<ResultDataEntity<T>> {
|
||||||
|
public ResultEntity(T data) {
|
||||||
|
super(new ResultDataEntity<>(HttpStatus.OK, data), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultEntity(HttpStatus status, T data) {
|
||||||
|
super(new ResultDataEntity<>(status, data), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultEntity(HttpStatus status, String msg, T data) {
|
||||||
|
super(new ResultDataEntity<>(status, msg, data), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultEntity(String msg) {
|
||||||
|
super(new ResultDataEntity<>(HttpStatus.OK, msg), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultEntity(HttpStatus status, String msg) {
|
||||||
|
super(new ResultDataEntity<>(status, msg), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultEntity(HttpStatus status) {
|
||||||
|
super(new ResultDataEntity<>(status), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultEntity(HttpStatus status, Flux<String> flow) {
|
||||||
|
super(new ResultDataEntity<>(status, flow), status);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
-- Execute the duplicate check first. It must return no rows before adding the constraint.
|
||||||
|
SELECT request_id, COUNT(*) AS duplicate_count
|
||||||
|
FROM currency_generation_verification
|
||||||
|
GROUP BY request_id
|
||||||
|
HAVING COUNT(*) > 1;
|
||||||
|
|
||||||
|
-- MySQL 8+: add the business uniqueness constraint to an existing table.
|
||||||
|
ALTER TABLE currency_generation_verification
|
||||||
|
ADD CONSTRAINT uk_currency_verification_request UNIQUE (request_id);
|
||||||
Loading…
Reference in New Issue