fix: 优化逻辑

This commit is contained in:
tangwei 2026-05-09 08:29:58 +08:00
parent 9c52bb1c73
commit 76821ca786
2 changed files with 96 additions and 12 deletions

View File

@ -3,7 +3,9 @@ package com.yfd.platform.data.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -495,6 +497,9 @@ public class FishDraftDataController {
@GetMapping("/previewFile")
@Operation(summary = "预览临时文件内容")
public void previewFile(@RequestParam String taskId, @RequestParam String filename, @RequestParam String type, HttpServletRequest request, HttpServletResponse response) {
// 解码 URL 编码的 filename处理中文文件名
String decodedFilename = URLDecoder.decode(filename, StandardCharsets.UTF_8);
log.debug("原始文件名: {}, 解码后: {}", filename, decodedFilename);
ImportTask importTask = importTaskService.getById(taskId);
String resultJson = importTask.getResultJson();
@ -502,9 +507,9 @@ public class FishDraftDataController {
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;
// FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
String tempDir = importTask.getTempDir();
filePath = tempDir + File.separator + dir + File.separator + decodedFilename;
} catch (Exception e) {
e.printStackTrace();
// ignore parse error

View File

@ -1,5 +1,7 @@
package com.yfd.platform.data.utils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@ -364,22 +366,99 @@ public class ZipFileUtil {
}
private static String saveFileToDir(InputStream is, File tempDir, String subFolder, String fileName) throws IOException {
// 使用 Hutool 构建文件路径
String safeFileName = sanitizeFileName(fileName);
File folder = new File(tempDir, subFolder);
if (!folder.exists()) {
folder.mkdirs();
// 使用 Hutool 创建目录会自动创建父目录
FileUtil.mkdir(folder);
log.info("保存文件: fileName{} -> safeFileName{}->subFolder{}", fileName, safeFileName,subFolder);
// 构建完整文件路径
File file = new File(folder, safeFileName);
// 安全检查防止目录穿越
String canonicalPath = file.getCanonicalPath();
String canonicalDir = folder.getCanonicalPath();
if (!canonicalPath.startsWith(canonicalDir)) {
throw new IOException("非法的文件路径: " + fileName);
}
File file = new File(folder, fileName);
try (FileOutputStream fos = new FileOutputStream(file)) {
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
// 使用 Hutool 从流复制到文件
try {
FileUtil.writeFromStream(is, file);
log.debug("保存文件: {} -> {}, 大小: {} bytes", fileName, safeFileName, file.length());
} catch (Exception e) {
throw new IOException("保存文件失败: " + fileName, e);
}
return file.getAbsolutePath();
}
/**
* 清理和标准化文件名确保在 Linux 上正确显示中文
*/
private static String sanitizeFileName(String fileName) {
if (StrUtil.isBlank(fileName)) {
return "unnamed_" + System.currentTimeMillis();
}
// 使用 Hutool 去除首尾空格
String sanitized = StrUtil.trim(fileName);
// 替换非法字符Linux/Windows 都不允许的字符
sanitized = sanitized.replaceAll("[\\\\/:*?\"<>|]", "_");
// 去除连续的下划线
sanitized = sanitized.replaceAll("_+", "_");
// 如果文件名过长截断Linux 文件名最大 255 字节
byte[] bytes = sanitized.getBytes(StandardCharsets.UTF_8);
if (bytes.length > 200) {
String extension = "";
int dotIndex = sanitized.lastIndexOf('.');
if (dotIndex > 0 && dotIndex < sanitized.length() - 1) {
extension = sanitized.substring(dotIndex);
sanitized = sanitized.substring(0, dotIndex);
}
// 重新计算长度
bytes = sanitized.getBytes(StandardCharsets.UTF_8);
int maxNameLength = 200 - extension.getBytes(StandardCharsets.UTF_8).length;
if (bytes.length > maxNameLength) {
// 安全截断避免切断多字节字符
sanitized = StrUtil.subPre(sanitized, maxNameLength);
}
sanitized = sanitized + extension;
}
// 确保文件名不为空
if (StrUtil.isBlank(sanitized) || ".".equals(sanitized)) {
return "file_" + System.currentTimeMillis();
}
return sanitized;
}
// private static String saveFileToDir(InputStream is, File tempDir, String subFolder, String fileName) throws IOException {
// File folder = new File(tempDir, subFolder);
// if (!folder.exists()) {
// folder.mkdirs();
// }
//
// File file = new File(folder, fileName);
// try (FileOutputStream fos = new FileOutputStream(file)) {
// byte[] buffer = new byte[4096];
// int len;
// while ((len = is.read(buffer)) > 0) {
// fos.write(buffer, 0, len);
// }
// }
// return file.getAbsolutePath();
// }
private static boolean isImageFile(String fileName) {
return fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") ||
fileName.endsWith(".png") || fileName.endsWith(".gif") ||