| | |
| | | import com.lxzn.framework.exception.ExceptionCast; |
| | | import com.lxzn.framework.utils.SHA256Util; |
| | | import com.lxzn.framework.utils.date.DateUtil; |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | |
| | | import java.net.URLEncoder; |
| | | import java.nio.channels.FileChannel; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.security.MessageDigest; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | |
| | | public class FileUtil { |
| | | |
| | | private static String fileUploadFolder; |
| | | private static String fileNcGateway; |
| | | @Value("${fileNcGateway}") |
| | | public void setFileNcGateway(String fileNcGateway) { |
| | | FileUtil.fileNcGateway = fileNcGateway; |
| | | } |
| | | |
| | | @Value("${fileHomePath}") |
| | | public void setFileUploadFolder(String fileUploadFolder) { |
| | |
| | | dto.setFileSize(fileSize); |
| | | dto.setFileSuffix(suffix); |
| | | return dto; |
| | | } |
| | | |
| | | /** |
| | | * 方法一:使用 FileWriter 写文件 |
| | | * @param filepath 文件目录 |
| | | * @param content 待写入内容 |
| | | * @throws IOException |
| | | */ |
| | | public static void fileWriterSql(String filepath, String content) throws IOException { |
| | | OutputStreamWriter outputStreamWriter = null; |
| | | try { |
| | | File file = new File(filepath); |
| | | if (!file.exists()){ |
| | | file.createNewFile(); |
| | | } |
| | | FileOutputStream outputStream = new FileOutputStream(file); |
| | | if (outputStream != null){ |
| | | outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8"); |
| | | outputStreamWriter.write(content); |
| | | outputStreamWriter.flush(); |
| | | } |
| | | try { |
| | | if (outputStreamWriter != null){ |
| | | outputStreamWriter.close(); |
| | | } |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | catch (IOException e) { |
| | | e.getMessage(); |
| | | } |
| | | finally { |
| | | try { |
| | | if (outputStreamWriter != null){ |
| | | outputStreamWriter.close(); |
| | | } |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 删除文件 |
| | | * |
| | | * @param filePath |
| | | * @return |
| | | */ |
| | | public static boolean deleteNcFile(String filePath) { |
| | | String lastFileReName = fileUploadFolder + "/" + filePath ; |
| | | boolean flag = false; |
| | | File file = new File(lastFileReName); |
| | | if (!file.exists()) { |
| | | return flag; |
| | | } |
| | | boolean b = file.delete(); |
| | | if (!b) { |
| | | System.out.println("文件删除失败: " + filePath); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 复制文件(带重试、大小校验和MD5校验,确保复制完整性与可靠性) |
| | | * 从 fileUploadFolder 下的源路径复制到 fileNcGateway 下的目标路径,可指定新的文件扩展名 |
| | | * @param lastFile 源文件的相对路径(相对于 fileUploadFolder) |
| | | * @param newFile 目标文件的相对路径(相对于 fileNcGateway) |
| | | * @param ncFix (可选)目标文件的新扩展名(不带点,如 "txt"),传入 null 或空字符串则不修改原扩展名 |
| | | * @return 复制成功返回 true,否则返回 false |
| | | */ |
| | | public static boolean copyFileUpName(String lastFile, String newFile, String ncFix) { |
| | | // 1. 构建源文件和目标文件的绝对路径 |
| | | String sourceFilePath = fileUploadFolder + "/" + lastFile; |
| | | String targetFilePath = fileNcGateway + "/" + newFile; |
| | | |
| | | // 2. 如果指定了新的扩展名,则附加到目标文件名 |
| | | if (StringUtils.isNotBlank(ncFix)) { |
| | | targetFilePath = targetFilePath + "." + ncFix; |
| | | } |
| | | |
| | | // 3. 创建目标文件夹 |
| | | File targetFile = new File(targetFilePath); |
| | | File targetParentDir = targetFile.getParentFile(); |
| | | if (!targetParentDir.exists() && !targetParentDir.mkdirs()) { |
| | | log.error("无法创建目标文件夹: {}", targetParentDir.getAbsolutePath()); |
| | | return false; |
| | | } |
| | | |
| | | // 4. 获取源文件预期大小 |
| | | long expectedSize = -1; |
| | | File sourceFile = new File(sourceFilePath); |
| | | if (!sourceFile.exists()) { |
| | | log.error("源文件不存在: {}", sourceFilePath); |
| | | return false; |
| | | } |
| | | try { |
| | | expectedSize = sourceFile.length(); |
| | | log.info("文件复制: 源={}, 目标={}, 大小={}字节", sourceFilePath, targetFilePath, expectedSize); |
| | | } catch (SecurityException e) { |
| | | log.error("无法访问源文件: {}", sourceFilePath, e); |
| | | return false; |
| | | } |
| | | |
| | | // 5. 复制操作(最多重试3次) |
| | | int maxRetries = 3; |
| | | int attempt = 0; |
| | | boolean copySuccess = false; |
| | | |
| | | while (attempt < maxRetries && !copySuccess) { |
| | | attempt++; |
| | | try { |
| | | log.info("---- 开始第{}次复制尝试 ----", attempt); |
| | | |
| | | // 6. 执行复制操作(使用NIO FileChannel以提高效率) |
| | | long startTime = System.currentTimeMillis(); |
| | | try (FileChannel in = new FileInputStream(sourceFilePath).getChannel(); |
| | | FileChannel out = new FileOutputStream(targetFilePath).getChannel()) { |
| | | out.transferFrom(in, 0, in.size()); |
| | | } |
| | | long endTime = System.currentTimeMillis(); |
| | | log.info("文件传输完成,耗时: {}毫秒", (endTime - startTime)); |
| | | |
| | | // 7. 文件大小验证 |
| | | File copiedFile = new File(targetFilePath); |
| | | long actualSize = copiedFile.length(); |
| | | |
| | | if (expectedSize != actualSize) { |
| | | log.warn("大小不一致! 预期: {}B, 实际: {}B (差值: {}B)", |
| | | expectedSize, actualSize, Math.abs(actualSize - expectedSize)); |
| | | } else { |
| | | log.info("文件大小验证成功: {}B", actualSize); |
| | | copySuccess = true; |
| | | } |
| | | |
| | | // 8. MD5校验 |
| | | if (copySuccess) { |
| | | String sourceMd5 = calculateMD5(sourceFilePath); |
| | | String targetMd5 = calculateMD5(targetFilePath); |
| | | |
| | | if (!sourceMd5.equals(targetMd5)) { |
| | | log.warn("MD5不一致! 源: {}, 目标: {}", sourceMd5, targetMd5); |
| | | copySuccess = false; |
| | | } else { |
| | | log.info("MD5验证成功"); |
| | | } |
| | | } |
| | | |
| | | } catch (IOException | SecurityException e) { |
| | | log.error("第{}次复制失败", attempt, e); |
| | | } |
| | | |
| | | // 9. 重试间隔处理 |
| | | if (!copySuccess && attempt < maxRetries) { |
| | | try { |
| | | int delay = 200 * attempt; // 递增延迟:200ms, 400ms |
| | | log.info("等待 {}ms 后重试", delay); |
| | | Thread.sleep(delay); |
| | | } catch (InterruptedException ie) { |
| | | Thread.currentThread().interrupt(); |
| | | log.warn("重试等待被中断", ie); |
| | | break; // 如果线程被中断,则退出重试循环 |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (copySuccess) { |
| | | log.info("文件复制完成: {}", targetFilePath); |
| | | } else { |
| | | log.error("文件复制失败,已尝试{}次。源文件: {}, 目标文件: {}", maxRetries, sourceFilePath, targetFilePath); |
| | | } |
| | | |
| | | return copySuccess; |
| | | } |
| | | |
| | | public static FileUploadResult uploadFile(String fileName, InputStream fis) { |
| | |
| | | log.error(e.getMessage()); |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 删除文件 |
| | | * |
| | | * @param filePath |
| | | * @return |
| | | */ |
| | | public static boolean deleteFile(String filePath) { |
| | | boolean flag = false; |
| | | File file = new File(filePath); |
| | | if (!file.exists()) { |
| | | return flag; |
| | | } |
| | | boolean b = file.delete(); |
| | | if (!b) { |
| | | try { |
| | | System.gc(); |
| | | Path path = Paths.get(filePath); |
| | | Files.deleteIfExists(path); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * |
| | | * @param file |
| | | * @return |
| | | */ |
| | | public static long selectFileSize(File file) { |
| | | try (FileInputStream fis = new FileInputStream(file)) { |
| | | long size = 0; |
| | | int read; |
| | | byte[] buffer = new byte[1024]; |
| | | while ((read = fis.read(buffer)) != -1) { |
| | | size += read; |
| | | } |
| | | return size; |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | public static String getFileAbsPath(String path, String fileName){ |
| | | path = fileUploadFolder + path; |
| | | File file = new File(path, fileName); |
| | |
| | | return null; |
| | | } |
| | | |
| | | public static String getFileAbsPathTxt(String path){ |
| | | File file = new File(path); |
| | | if(file.exists()){ |
| | | return file.getAbsolutePath(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |