add:新增日志管理,日志下载功能。2.二维码下载。3.异常信息的导出导出功能。
This commit is contained in:
@@ -2,9 +2,11 @@ package org.nl.sys.modular.anomalyInfo.controller;
|
|||||||
|
|
||||||
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.EasyExcel;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.nl.config.language.LangProcess;
|
import org.nl.config.language.LangProcess;
|
||||||
import org.nl.exception.BadRequestException;
|
import org.nl.exception.BadRequestException;
|
||||||
import org.nl.logging.annotation.Log;
|
import org.nl.logging.annotation.Log;
|
||||||
|
import org.nl.response.WebResponse;
|
||||||
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
import org.nl.sys.modular.anomalyInfo.listener.ErrorHandlingListener;
|
import org.nl.sys.modular.anomalyInfo.listener.ErrorHandlingListener;
|
||||||
@@ -23,6 +25,8 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
@@ -66,7 +70,7 @@ public class AnomalyInfoController {
|
|||||||
EasyExcel.read(file.getInputStream(), ErrorInfo.class, listener)
|
EasyExcel.read(file.getInputStream(), ErrorInfo.class, listener)
|
||||||
.sheet() // 默认读取第一个sheet
|
.sheet() // 默认读取第一个sheet
|
||||||
.doRead();
|
.doRead();
|
||||||
return new ResponseEntity<>("操作成功",HttpStatus.OK);
|
return new ResponseEntity<>(WebResponse.requestOk(),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/importErrorHandlingExcel")
|
@PostMapping("/importErrorHandlingExcel")
|
||||||
@@ -85,7 +89,7 @@ public class AnomalyInfoController {
|
|||||||
EasyExcel.read(file.getInputStream(), ErrorHandling.class, listener)
|
EasyExcel.read(file.getInputStream(), ErrorHandling.class, listener)
|
||||||
.sheet() // 默认读取第一个sheet
|
.sheet() // 默认读取第一个sheet
|
||||||
.doRead();
|
.doRead();
|
||||||
return new ResponseEntity<>("操作成功",HttpStatus.OK);
|
return new ResponseEntity<>(WebResponse.requestOk(),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/importErrorImage")
|
@PostMapping("/importErrorImage")
|
||||||
@@ -112,7 +116,7 @@ public class AnomalyInfoController {
|
|||||||
parseZip.processCompressedFile(file);
|
parseZip.processCompressedFile(file);
|
||||||
|
|
||||||
|
|
||||||
return new ResponseEntity<>("上传成功!",HttpStatus.OK);
|
return new ResponseEntity<>(LangProcess.msg("successful"),HttpStatus.OK);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new BadRequestException(LangProcess.msg("anomaly_file_parse_failed",e.getMessage()));
|
throw new BadRequestException(LangProcess.msg("anomaly_file_parse_failed",e.getMessage()));
|
||||||
@@ -131,4 +135,36 @@ public class AnomalyInfoController {
|
|||||||
return new ResponseEntity<>(errorInfoService.updateErrorInfo(errorInfo),HttpStatus.OK);
|
return new ResponseEntity<>(errorInfoService.updateErrorInfo(errorInfo),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/exportErrorInfoExcel")
|
||||||
|
@Log("导出异常信息")
|
||||||
|
public void exportErrorInfoExcel(HttpServletResponse response) throws IOException {
|
||||||
|
|
||||||
|
List<ErrorInfo> taskInfoList = errorInfoService.exportErrorInfoExcel();
|
||||||
|
|
||||||
|
// 设置响应头
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(LangProcess.msg("error_info")+".xlsx", "UTF-8"));
|
||||||
|
|
||||||
|
// 使用EasyExcel写入数据到响应输出流
|
||||||
|
EasyExcel.write(response.getOutputStream(), ErrorInfo.class)
|
||||||
|
.sheet(LangProcess.msg("error_info"))
|
||||||
|
.doWrite(taskInfoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/exportErrorHandlingInfoExcel")
|
||||||
|
@Log("导出异常处理信息")
|
||||||
|
public void exportErrorHandlingInfoExcel(HttpServletResponse response) throws IOException {
|
||||||
|
|
||||||
|
List<ErrorHandling> taskInfoList = errorHandlingService.exportErrorHandlingInfoExcel();
|
||||||
|
|
||||||
|
// 设置响应头
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(LangProcess.msg("error_handling_info")+".xlsx", "UTF-8"));
|
||||||
|
|
||||||
|
// 使用EasyExcel写入数据到响应输出流
|
||||||
|
EasyExcel.write(response.getOutputStream(), ErrorHandling.class)
|
||||||
|
.sheet(LangProcess.msg("error_handling_info"))
|
||||||
|
.doWrite(taskInfoList);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,16 @@ package org.nl.sys.modular.anomalyInfo.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/29
|
* 2025/12/29
|
||||||
*/
|
*/
|
||||||
public interface ErrorHandlingService extends IService<ErrorHandling> {
|
public interface ErrorHandlingService extends IService<ErrorHandling> {
|
||||||
|
/**
|
||||||
|
* 导出异常处理信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<ErrorHandling> exportErrorHandlingInfoExcel();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import org.nl.response.WebResponse;
|
|||||||
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
import org.nl.sys.modular.anomalyInfo.param.QueryErrorInfoPageParam;
|
import org.nl.sys.modular.anomalyInfo.param.QueryErrorInfoPageParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/29
|
* 2025/12/29
|
||||||
@@ -24,4 +26,11 @@ public interface ErrorInfoService extends IService<ErrorInfo> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
WebResponse updateErrorInfo(ErrorInfo errorInfo);
|
WebResponse updateErrorInfo(ErrorInfo errorInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出异常信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<ErrorInfo> exportErrorInfoExcel();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,28 @@
|
|||||||
package org.nl.sys.modular.anomalyInfo.service.impl;
|
package org.nl.sys.modular.anomalyInfo.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
import org.nl.sys.modular.anomalyInfo.service.ErrorHandlingService;
|
import org.nl.sys.modular.anomalyInfo.service.ErrorHandlingService;
|
||||||
import org.nl.sys.modular.anomalyInfo.mapper.ErrorHandlingMapper;
|
import org.nl.sys.modular.anomalyInfo.mapper.ErrorHandlingMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/29
|
* 2025/12/29
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class ErrorHandlingServiceImpl extends ServiceImpl<ErrorHandlingMapper, ErrorHandling> implements ErrorHandlingService {
|
public class ErrorHandlingServiceImpl extends ServiceImpl<ErrorHandlingMapper, ErrorHandling> implements ErrorHandlingService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorHandlingMapper errorHandlingMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ErrorHandling> exportErrorHandlingInfoExcel() {
|
||||||
|
return errorHandlingMapper.selectList(new LambdaQueryWrapper<>(ErrorHandling.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import org.nl.sys.modular.anomalyInfo.service.ErrorInfoService;
|
|||||||
import org.nl.sys.modular.anomalyInfo.mapper.ErrorInfoMapper;
|
import org.nl.sys.modular.anomalyInfo.mapper.ErrorInfoMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/29
|
* 2025/12/29
|
||||||
@@ -45,4 +47,10 @@ public class ErrorInfoServiceImpl extends ServiceImpl<ErrorInfoMapper, ErrorInfo
|
|||||||
}
|
}
|
||||||
return WebResponse.requestOk();
|
return WebResponse.requestOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ErrorInfo> exportErrorInfoExcel() {
|
||||||
|
return errorInfoMapper.selectList(new LambdaQueryWrapper<>(ErrorInfo.class));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package org.nl.sys.modular.logging.controller;
|
||||||
|
|
||||||
|
import org.nl.exception.BadRequestException;
|
||||||
|
import org.nl.logging.annotation.Log;
|
||||||
|
import org.nl.sys.modular.logging.service.LogService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.InputStreamResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/11/3
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/logs")
|
||||||
|
public class LogController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LogService logService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志文件列表
|
||||||
|
*/
|
||||||
|
@Log("获取日志文件列表")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public ResponseEntity<Object> getLogFiles() {
|
||||||
|
try {
|
||||||
|
return new ResponseEntity<>(logService.getLogFiles(), HttpStatus.OK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BadRequestException("获取日志文件失败:"+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载日志文件
|
||||||
|
*/
|
||||||
|
@Log("下载日志文件")
|
||||||
|
@GetMapping("/download/{fileName}")
|
||||||
|
public ResponseEntity<Resource> downloadLogFile(@PathVariable String fileName) {
|
||||||
|
try {
|
||||||
|
File file = logService.getLogFile(fileName);
|
||||||
|
|
||||||
|
Path filePath = file.toPath();
|
||||||
|
Resource resource = new InputStreamResource(Files.newInputStream(filePath));
|
||||||
|
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
|
"attachment; filename=\"" + file.getName() + "\"")
|
||||||
|
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
.contentLength(file.length())
|
||||||
|
.body(resource);
|
||||||
|
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.nl.sys.modular.logging.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/11/3
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LogFileDTO {
|
||||||
|
private String fileName;
|
||||||
|
private String filePath;
|
||||||
|
private Long fileSize;
|
||||||
|
private LocalDateTime lastModified;
|
||||||
|
private String readableSize;
|
||||||
|
|
||||||
|
public LogFileDTO(String fileName, String filePath, Long fileSize, LocalDateTime lastModified) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.filePath = filePath;
|
||||||
|
this.fileSize = fileSize;
|
||||||
|
this.lastModified = lastModified;
|
||||||
|
this.readableSize = formatFileSize(fileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatFileSize(long size) {
|
||||||
|
if (size <= 0) return "0 B";
|
||||||
|
final String[] units = new String[]{"B", "KB", "MB", "GB"};
|
||||||
|
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
|
||||||
|
return String.format("%.1f %s", size / Math.pow(1024, digitGroups), units[digitGroups]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.nl.sys.modular.logging.service;
|
||||||
|
|
||||||
|
import org.nl.sys.modular.logging.dto.LogFileDTO;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/11/3
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class LogService {
|
||||||
|
|
||||||
|
@Value("${customize.log-dir}")
|
||||||
|
private String logDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志文件列表
|
||||||
|
*/
|
||||||
|
public List<LogFileDTO> getLogFiles() {
|
||||||
|
List<LogFileDTO> logFiles = new ArrayList<>();
|
||||||
|
File directory = new File(logDir);
|
||||||
|
|
||||||
|
if (!directory.exists() || !directory.isDirectory()) {
|
||||||
|
return logFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = directory.listFiles((dir, name) ->
|
||||||
|
name.endsWith(".log") || name.endsWith(".txt"));
|
||||||
|
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isFile()) {
|
||||||
|
LogFileDTO logFile = new LogFileDTO(
|
||||||
|
file.getName(),
|
||||||
|
file.getAbsolutePath(),
|
||||||
|
file.length(),
|
||||||
|
LocalDateTime.ofInstant(
|
||||||
|
Instant.ofEpochMilli(file.lastModified()),
|
||||||
|
ZoneId.systemDefault()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
logFiles.add(logFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按修改时间倒序排列
|
||||||
|
logFiles.sort((a, b) -> b.getLastModified().compareTo(a.getLastModified()));
|
||||||
|
return logFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志文件
|
||||||
|
*/
|
||||||
|
public File getLogFile(String fileName) {
|
||||||
|
// 防止路径遍历攻击
|
||||||
|
if (fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
|
||||||
|
throw new IllegalArgumentException("Invalid file name");
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(logDir, fileName);
|
||||||
|
if (!file.exists() || !file.isFile()) {
|
||||||
|
throw new RuntimeException("File not found: " + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保文件在日志目录内
|
||||||
|
if (!file.getAbsolutePath().startsWith(new File(logDir).getAbsolutePath())) {
|
||||||
|
throw new SecurityException("Access denied");
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,18 @@ import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam;
|
|||||||
import org.nl.sys.modular.qrcode.param.QueryQRCodeParam;
|
import org.nl.sys.modular.qrcode.param.QueryQRCodeParam;
|
||||||
import org.nl.sys.modular.qrcode.param.UpdateQRCodeParam;
|
import org.nl.sys.modular.qrcode.param.UpdateQRCodeParam;
|
||||||
import org.nl.sys.modular.qrcode.service.QRCodeService;
|
import org.nl.sys.modular.qrcode.service.QRCodeService;
|
||||||
|
import org.springframework.core.io.InputStreamResource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/22
|
* 2025/12/22
|
||||||
@@ -72,4 +79,30 @@ public class QRCodeController {
|
|||||||
public ResponseEntity<Object> taskOperationConfirm(@RequestParam String taskCode){
|
public ResponseEntity<Object> taskOperationConfirm(@RequestParam String taskCode){
|
||||||
return new ResponseEntity<>(qrCodeService.taskOperationConfirm(taskCode),HttpStatus.OK);
|
return new ResponseEntity<>(qrCodeService.taskOperationConfirm(taskCode),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载二维码文件
|
||||||
|
*/
|
||||||
|
@Log("下载二维码文件")
|
||||||
|
@GetMapping("/download/{fileName}")
|
||||||
|
public ResponseEntity<org.springframework.core.io.Resource> downloadQRCodeFile(@PathVariable String fileName) {
|
||||||
|
try {
|
||||||
|
File file = qrCodeService.getQRCdoeFile(fileName);
|
||||||
|
|
||||||
|
Path filePath = file.toPath();
|
||||||
|
org.springframework.core.io.Resource resource = new InputStreamResource(Files.newInputStream(filePath));
|
||||||
|
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
|
"attachment; filename=\"" + file.getName() + "\"")
|
||||||
|
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
.contentLength(file.length())
|
||||||
|
.body(resource);
|
||||||
|
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam;
|
|||||||
import org.nl.sys.modular.qrcode.param.QueryQRCodeParam;
|
import org.nl.sys.modular.qrcode.param.QueryQRCodeParam;
|
||||||
import org.nl.sys.modular.qrcode.param.UpdateQRCodeParam;
|
import org.nl.sys.modular.qrcode.param.UpdateQRCodeParam;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/22
|
* 2025/12/22
|
||||||
@@ -74,4 +76,11 @@ public interface QRCodeService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean verifyQRCodeByRoom(String room);
|
boolean verifyQRCodeByRoom(String room);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取二维码文件
|
||||||
|
* @param fileName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
File getQRCdoeFile(String fileName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsh
|
* @author dsh
|
||||||
* 2025/12/22
|
* 2025/12/22
|
||||||
@@ -176,4 +178,24 @@ public class QRCodeServiceImpl implements QRCodeService {
|
|||||||
.eq(QRcodeInfo::getRoom_code,room)
|
.eq(QRcodeInfo::getRoom_code,room)
|
||||||
)>0;
|
)>0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getQRCdoeFile(String fileName) {
|
||||||
|
// 防止路径遍历攻击
|
||||||
|
if (fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
|
||||||
|
throw new IllegalArgumentException("Invalid file name");
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(fileProperties.getPath().getQrcode(), fileName);
|
||||||
|
if (!file.exists() || !file.isFile()) {
|
||||||
|
throw new RuntimeException("File not found: " + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保文件在日志目录内
|
||||||
|
if (!file.getAbsolutePath().startsWith(new File(fileProperties.getPath().getQrcode()).getAbsolutePath())) {
|
||||||
|
throw new SecurityException("Access denied");
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ task_confirm_arrival_failed = 任务到达确认失败
|
|||||||
task_next_station_failed = 任务下一站失败:{0}
|
task_next_station_failed = 任务下一站失败:{0}
|
||||||
|
|
||||||
# 异常信息相关
|
# 异常信息相关
|
||||||
|
error_info = 异常信息
|
||||||
|
error_handling_info = 异常处理信息
|
||||||
anomaly_file_not_selected = 请选择文件上传
|
anomaly_file_not_selected = 请选择文件上传
|
||||||
anomaly_file_name_empty = 文件名称为空
|
anomaly_file_name_empty = 文件名称为空
|
||||||
anomaly_file_format_error = 目前只支持ZIP格式
|
anomaly_file_format_error = 目前只支持ZIP格式
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ task_confirm_arrival_failed = Failed to confirm task arrival
|
|||||||
task_next_station_failed = Failed to go to next station:{0}
|
task_next_station_failed = Failed to go to next station:{0}
|
||||||
|
|
||||||
# Anomaly related
|
# Anomaly related
|
||||||
|
error_info = Anomaly information
|
||||||
|
error_handling_info = Exception handling information
|
||||||
anomaly_file_not_selected = Please select a file to upload
|
anomaly_file_not_selected = Please select a file to upload
|
||||||
anomaly_file_name_empty = File name is empty
|
anomaly_file_name_empty = File name is empty
|
||||||
anomaly_file_format_error = Currently only ZIP format is supported
|
anomaly_file_format_error = Currently only ZIP format is supported
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ task_confirm_arrival_failed = 任务到达确认失败
|
|||||||
task_next_station_failed = 任务下一站失败:{0}
|
task_next_station_failed = 任务下一站失败:{0}
|
||||||
|
|
||||||
# 异常信息相关
|
# 异常信息相关
|
||||||
|
error_info = 异常信息
|
||||||
|
error_handling_info = 异常处理信息
|
||||||
anomaly_file_not_selected = 请选择文件上传
|
anomaly_file_not_selected = 请选择文件上传
|
||||||
anomaly_file_name_empty = 文件名称为空
|
anomaly_file_name_empty = 文件名称为空
|
||||||
anomaly_file_format_error = 目前只支持ZIP格式
|
anomaly_file_format_error = 目前只支持ZIP格式
|
||||||
|
|||||||
Reference in New Issue
Block a user