fix: 优化逻辑
This commit is contained in:
parent
9c52bb1c73
commit
76821ca786
@ -3,7 +3,9 @@ package com.yfd.platform.data.controller;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@ -495,6 +497,9 @@ public class FishDraftDataController {
|
|||||||
@GetMapping("/previewFile")
|
@GetMapping("/previewFile")
|
||||||
@Operation(summary = "预览临时文件内容")
|
@Operation(summary = "预览临时文件内容")
|
||||||
public void previewFile(@RequestParam String taskId, @RequestParam String filename, @RequestParam String type, HttpServletRequest request, HttpServletResponse response) {
|
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);
|
ImportTask importTask = importTaskService.getById(taskId);
|
||||||
String resultJson = importTask.getResultJson();
|
String resultJson = importTask.getResultJson();
|
||||||
@ -502,9 +507,9 @@ public class FishDraftDataController {
|
|||||||
String dir = "1".equals(type) ? "images" : "videos";
|
String dir = "1".equals(type) ? "images" : "videos";
|
||||||
if (resultJson != null && !resultJson.isEmpty()) {
|
if (resultJson != null && !resultJson.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
|
// FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
|
||||||
String tempDir = importResult.getTempDir();
|
String tempDir = importTask.getTempDir();
|
||||||
filePath = tempDir + File.separator + dir + File.separator + filename;
|
filePath = tempDir + File.separator + dir + File.separator + decodedFilename;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
// ignore parse error
|
// ignore parse error
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.yfd.platform.data.utils;
|
package com.yfd.platform.data.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
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 {
|
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);
|
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);
|
// 使用 Hutool 从流复制到文件
|
||||||
try (FileOutputStream fos = new FileOutputStream(file)) {
|
try {
|
||||||
byte[] buffer = new byte[4096];
|
FileUtil.writeFromStream(is, file);
|
||||||
int len;
|
log.debug("保存文件: {} -> {}, 大小: {} bytes", fileName, safeFileName, file.length());
|
||||||
while ((len = is.read(buffer)) > 0) {
|
} catch (Exception e) {
|
||||||
fos.write(buffer, 0, len);
|
throw new IOException("保存文件失败: " + fileName, e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return file.getAbsolutePath();
|
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) {
|
private static boolean isImageFile(String fileName) {
|
||||||
return fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") ||
|
return fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") ||
|
||||||
fileName.endsWith(".png") || fileName.endsWith(".gif") ||
|
fileName.endsWith(".png") || fileName.endsWith(".gif") ||
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user