fix: 优化导文件预览

This commit is contained in:
tangwei 2026-04-30 08:50:09 +08:00
parent a8521c554c
commit 91b14b3e3e
3 changed files with 203 additions and 12 deletions

View File

@ -54,6 +54,7 @@ public class SecurityConfig {
.requestMatchers("/user/login").anonymous() .requestMatchers("/user/login").anonymous()
.requestMatchers("/user/code").permitAll() .requestMatchers("/user/code").permitAll()
.requestMatchers("/sms/resetPassword").permitAll() .requestMatchers("/sms/resetPassword").permitAll()
.requestMatchers("/data/fishDraft/previewFile").permitAll()
.requestMatchers("/tempFile/**").permitAll() .requestMatchers("/tempFile/**").permitAll()
.requestMatchers("/system/user/auditUser").permitAll() .requestMatchers("/system/user/auditUser").permitAll()
.requestMatchers("/eng/**").permitAll() .requestMatchers("/eng/**").permitAll()

View File

@ -1,5 +1,15 @@
package com.yfd.platform.data.controller; package com.yfd.platform.data.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceRequest;
@ -21,6 +31,8 @@ import com.yfd.platform.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -168,7 +180,6 @@ public class FishDraftDataController {
} }
@PostMapping("/lockDraft") @PostMapping("/lockDraft")
@Operation(summary = "锁定草稿") @Operation(summary = "锁定草稿")
public ResponseResult lockDraft(@RequestParam String id) { public ResponseResult lockDraft(@RequestParam String id) {
@ -275,6 +286,182 @@ public class FishDraftDataController {
} }
} }
@GetMapping("/previewTempFiles")
@Operation(summary = "预览临时文件列表")
public ResponseResult previewTempFiles(@RequestParam String taskId) {
if (taskId == null || taskId.isEmpty()) {
return ResponseResult.error("任务ID不能为空");
}
try {
ImportTask task = importTaskService.getById(taskId);
if (task == null) {
return ResponseResult.error("任务不存在");
}
String resultJson = task.getResultJson();
if (resultJson == null || resultJson.isEmpty()) {
return ResponseResult.error("任务结果为空");
}
FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
Map<String, Object> previewData = new HashMap<>();
previewData.put("tempDir", importResult.getTempDir());
previewData.put("excelFileName", importResult.getExcelFileName());
previewData.put("excelFilePath", importResult.getExcelFilePath());
List<Map<String, String>> imageList = new ArrayList<>();
if (importResult.getImageFiles() != null) {
for (Map.Entry<String, String> entry : importResult.getImageFiles().entrySet()) {
Map<String, String> fileInfo = new HashMap<>();
fileInfo.put("originalName", entry.getKey());
fileInfo.put("path", entry.getValue());
fileInfo.put("type", "image");
imageList.add(fileInfo);
}
}
previewData.put("images", imageList);
List<Map<String, String>> videoList = new ArrayList<>();
if (importResult.getVideoFiles() != null) {
for (Map.Entry<String, String> entry : importResult.getVideoFiles().entrySet()) {
Map<String, String> fileInfo = new HashMap<>();
fileInfo.put("originalName", entry.getKey());
fileInfo.put("path", entry.getValue());
fileInfo.put("type", "video");
videoList.add(fileInfo);
}
}
previewData.put("videos", videoList);
previewData.put("totalImages", imageList.size());
previewData.put("totalVideos", videoList.size());
return ResponseResult.successData(previewData);
} catch (Exception e) {
log.error("预览临时文件失败: " + e.getMessage(), e);
return ResponseResult.error("预览失败: " + e.getMessage());
}
}
@GetMapping("/previewFile")
@Operation(summary = "预览临时文件内容")
public void previewFile(@RequestParam String taskId, @RequestParam String filename, @RequestParam String type, HttpServletRequest request, HttpServletResponse response) {
ImportTask importTask = importTaskService.getById(taskId);
String resultJson = importTask.getResultJson();
String filePath = null;
String dir = "1".equals(type) ? "images" : "videos";
if (resultJson != null && !resultJson.isEmpty()) {
try {
FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
String tempDir = importResult.getTempDir();
filePath = tempDir + File.separator + dir + File.separator + filename;
} catch (Exception e) {
e.printStackTrace();
// ignore parse error
}
}
if (filePath == null) {
writeErrorResponse(response, "文件路径不能为空");
return;
}
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
writeErrorResponse(response, "文件不存在");
return;
}
try {
String fileName = file.getName();
String contentType = request.getServletContext().getMimeType(fileName);
if (contentType == null) {
contentType = "application/octet-stream";
}
response.setContentType(contentType);
response.setHeader("Content-Disposition", "inline; filename=\"" + URLEncoder.encode(fileName, "UTF-8") + "\"");
response.setContentLengthLong(file.length());
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.flush();
}
} catch (Exception e) {
log.error("预览文件失败: " + e.getMessage(), e);
writeErrorResponse(response, "预览失败: " + e.getMessage());
}
}
@GetMapping("/previewFileBase64")
@Operation(summary = "预览临时文件内容(Base64方式)")
public ResponseResult previewFileBase64(@RequestParam String filePath) {
if (filePath == null || filePath.isEmpty()) {
return ResponseResult.error("文件路径不能为空");
}
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
return ResponseResult.error("文件不存在");
}
try {
String fileName = file.getName();
String contentType = getMimeType(fileName);
byte[] fileContent = Files.readAllBytes(file.toPath());
String base64Content = Base64.getEncoder().encodeToString(fileContent);
Map<String, Object> result = new HashMap<>();
result.put("fileName", fileName);
result.put("contentType", contentType);
result.put("base64Content", base64Content);
result.put("size", file.length());
return ResponseResult.successData(result);
} catch (Exception e) {
log.error("预览文件失败: " + e.getMessage(), e);
return ResponseResult.error("预览失败: " + e.getMessage());
}
}
private void writeErrorResponse(HttpServletResponse response, String message) {
try {
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"success\":false,\"message\":\"" + message + "\"}");
} catch (Exception ignored) {
}
}
private String getMimeType(String fileName) {
if (fileName == null) return "application/octet-stream";
String lowerName = fileName.toLowerCase();
if (lowerName.endsWith(".jpg") || lowerName.endsWith(".jpeg")) {
return "image/jpeg";
} else if (lowerName.endsWith(".png")) {
return "image/png";
} else if (lowerName.endsWith(".gif")) {
return "image/gif";
} else if (lowerName.endsWith(".mp4")) {
return "video/mp4";
} else if (lowerName.endsWith(".webm")) {
return "video/webm";
} else if (lowerName.endsWith(".pdf")) {
return "application/pdf";
} else if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
return "application/octet-stream";
}
@PostMapping("/cancelImport") @PostMapping("/cancelImport")
@Operation(summary = "取消导入任务") @Operation(summary = "取消导入任务")
public ResponseResult cancelImport(@RequestBody FishImportRequest fishImportRequest) { public ResponseResult cancelImport(@RequestBody FishImportRequest fishImportRequest) {

View File

@ -200,6 +200,9 @@ public class ImportTaskServiceImpl extends ServiceImpl<ImportTaskMapper, ImportT
fileIds.forEach(fileId -> attachmentUploadService.deleteFile(fileId)); fileIds.forEach(fileId -> attachmentUploadService.deleteFile(fileId));
} }
} }
String tempDir = importResult.getTempDir();
// del 方法会递归删除目录及其所有内容
FileUtil.del(tempDir);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
// ignore parse error // ignore parse error