lyh
10 天以前 30c9299fa9ffc8d3cd51d4a18b4c0b33c3ef8141
修改
已修改3个文件
316 ■■■■ 文件已修改
pom.xml 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/lxzn/activiti/service/impl/AssignFileStreamServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/lxzn/framework/utils/file/FileUtil.java 269 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -71,22 +71,22 @@
        <!--spring boot 结束-->
        <!--持久层 数据库 连接池 开始-->
        <!--数据库连接在springboot中定义了,所以可以管理包的版本-->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>com.microsoft.sqlserver</groupId>-->
<!--            <artifactId>mssql-jdbc</artifactId>-->
<!--            <scope>runtime</scope>-->
<!--        </dependency>-->
        <!-- <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <version>${mysql-connector-java.version}</version>
         </dependency>-->
        <!--   达梦数据库     -->
<!--        <dependency>-->
<!--            <groupId>com.dameng</groupId>-->
<!--            <artifactId>DmJdbcDriver18</artifactId>-->
<!--            <version>8.1.1.193</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.dameng</groupId>
            <artifactId>DmJdbcDriver18</artifactId>
            <version>8.1.1.193</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
@@ -236,6 +236,27 @@
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>2.3.1</version>
        </dependency>
    </dependencies>
src/main/java/com/lxzn/activiti/service/impl/AssignFileStreamServiceImpl.java
@@ -892,7 +892,7 @@
        String id = IdWorker.getIdStr();
        String name = DateUtil.format(DateUtil.getNow(),DateUtil.STR_YEARMONTHDAY);
        String newPath = "/securedoc" + docFile.getFilePath();
        String loFilePath = fileHomePath + newPath +  "\\" + name +"_" + id;
        String loFilePath = fileHomePath + newPath +  "/" + name +"_" + id;
        ObjectMapper mapper = new ObjectMapper();
        try {
            String json = mapper.writeValueAsString(source);
@@ -955,7 +955,7 @@
        equipmentTask.setDocVersion(docFile.getDocVersion());
        equipmentTask.setFileName(docInfo.getDocName());
        equipmentTask.setFileEncodeName(docFile.getFileEncodeName());
        equipmentTask.setFilePath(docFile.getFilePath());
        equipmentTask.setFilePath(newPath);
        equipmentTask.setFileSuffix(docFile.getFileSuffix());
        equipmentTask.setFileSize(docFile.getFileSize());
        b = equipmentTaskService.save(equipmentTask);
@@ -992,7 +992,7 @@
        equipmentTaskTxt.setDocVersion("a.1");
        equipmentTaskTxt.setFileName( name +"_" + id);
        equipmentTaskTxt.setFileEncodeName( name +"_" + id);
        equipmentTaskTxt.setFilePath(docFile.getFilePath());
        equipmentTaskTxt.setFilePath(newPath);
        equipmentTaskTxt.setFileSuffix("txt");
        equipmentTaskTxt.setFileSize(FileUtil.selectFileSize(new File(loFilePath)));
        boolean txt = equipmentTaskService.save(equipmentTaskTxt);
src/main/java/com/lxzn/framework/utils/file/FileUtil.java
@@ -19,7 +19,6 @@
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;
import java.util.List;
@@ -29,11 +28,7 @@
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) {
@@ -131,116 +126,28 @@
        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 = newFile;
        // 2. 如果指定了新的扩展名,则附加到目标文件名
        String lastFileReName =  fileUploadFolder + "/" + lastFile ;
        if (StringUtils.isNotBlank(ncFix)) {
            targetFilePath = targetFilePath + "." + ncFix;
            newFile =  newFile + "." + 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;
        File toFile = new File(newFile);
        if (!toFile.getParentFile().exists()) {
            toFile.mkdirs();
        }
        try {
            expectedSize = sourceFile.length();
            log.info("文件复制: 源={}, 目标={}, 大小={}字节", sourceFilePath, targetFilePath, expectedSize);
        } catch (SecurityException e) {
            log.error("无法访问源文件: {}", sourceFilePath, e);
            long begintime = System.currentTimeMillis(); // 获取拷贝文件前的系统时间
            Files.copy(Paths.get(lastFileReName),
                    Paths.get(newFile),
                    StandardCopyOption.REPLACE_EXISTING);
            long endtime = System.currentTimeMillis(); // 获取文件拷贝结束时的系统时间
            System.out.println("拷贝文件所消耗的时间是:" + (endtime - begintime) + "毫秒");
            return true;
        }
        catch (Exception e) {
            e.printStackTrace();
            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) {
@@ -536,133 +443,41 @@
    }
    /**
     * 复制文件(带重试和校验-防止中科方德复制文件出错问题)
     * 复制文件
     * @param oldPath
     * @param newPath
     * @param fileName
     */
    public static boolean copyFile(String oldPath, String newPath, String fileName){
        // 1. 路径规范化
        String absolutePathSend = fileUploadFolder + oldPath;
        String absolutePathTarget = fileUploadFolder + newPath;
        // 2. 创建目标文件夹
        File targetFolder = new File(absolutePathTarget);
        if (!targetFolder.exists() && !targetFolder.mkdirs()) {
            log.error("无法创建目标文件夹: {}", absolutePathTarget);
            return false;
        oldPath = fileUploadFolder + oldPath;
        newPath = fileUploadFolder + newPath;
        File oldFile = new File(oldPath, fileName);
        File newFile = new File(newPath, fileName);
        if(oldFile.exists()){
            if(!newFile.getParentFile().exists()){
                newFile.getParentFile().mkdirs();
        }
        // 3. 源文件和目标文件路径
        String sourceFilePath = absolutePathSend + File.separator + fileName;
        String targetFilePath = absolutePathTarget + File.separator + fileName;
        // 4. 获取源文件预期大小
        long expectedSize = -1;
        File sourceFile = new File(sourceFilePath);
        if (!sourceFile.exists()) {
            log.error("源文件不存在: {}", sourceFilePath);
            return false;
        }
            FileChannel inputChannel = null;
            FileChannel outputChannel = null;
        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. 执行复制操作
                try (FileChannel in = new FileInputStream(sourceFilePath).getChannel();
                     FileChannel out = new FileOutputStream(targetFilePath).getChannel()) {
                    out.transferFrom(in, 0, in.size());
                }
                // 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();
                }
            }
        }
        if (copySuccess) {
            log.info("文件复制完成: {}", targetFilePath);
        } else {
            log.error("文件复制失败,已尝试{}次", maxRetries);
        }
        return copySuccess;
    }
    /**
     * 计算文件的MD5值
     * @param filePath
     * @return
     */
    public static String calculateMD5(String filePath) {
        try (InputStream is = Files.newInputStream(Paths.get(filePath))) {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] buffer = new byte[8192];
            int read;
            while ((read = is.read(buffer)) != -1) {
                md.update(buffer, 0, read);
            }
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
                inputChannel = new FileInputStream(oldFile).getChannel();
                outputChannel = new FileOutputStream(newFile).getChannel();
                outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
                return true;
        } catch (Exception e) {
            throw new RuntimeException("计算MD5失败: " + filePath, e);
                log.error("复制文件错误{}", e);
                return false;
            }finally {
                try {
                    inputChannel.close();
                    outputChannel.close();
                }catch (Exception e){
                    log.error("复制文件错误{}", e);
        }
            }
        }
        return false;
    }
    public static String getFileAbsPath(String path, String fileName){