package com.product.file.util; import cn.hutool.core.lang.UUID; import com.aspose.words.Document; import com.aspose.words.SaveFormat; import com.google.common.collect.Maps; import com.product.common.lang.StringUtils; import com.product.core.config.Global; import com.product.core.exception.BaseException; import com.product.file.config.CmnConst; import com.product.file.config.FileCode; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * Copyright © 6c * * @Date: 2021-03-05 10:59 * @Author: 6c * @Description: */ @Slf4j public class FileUtil { private FileUtil() { } public static void main(String[] args) { System.out.println(FileUtil.checkDocType(new File("D:\\downloads\\关于协调解决西宁万达地产置业有限公司商品房预售资金监管账户冻结相关问题 (1).doc"))); } public static String checkDocType(File file) { try (FileInputStream fis = new FileInputStream(file)) { byte[] bytes = new byte[8]; fis.read(bytes, 0, 8); String hex = bytesToHex(bytes); if (hex.contains("504B0304") && (file.getName().endsWith(".doc") || file.getName().endsWith(".docx"))) { return "docx"; } else if (hex.contains("D0CF11E0") && (file.getName().endsWith(".doc") || file.getName().endsWith(".docx"))) { //因为doc文件的头部也是D0CF11E0,所以需要判断文件后缀 return "doc"; } //增加xls 和 xlsx的判断 else if (hex.contains("504B0304") && (file.getName().endsWith(".xls") || file.getName().endsWith(".xlsx"))) { return "xlsx"; } else if (hex.contains("D0CF11E0") && (file.getName().endsWith(".xls") || file.getName().endsWith(".xlsx"))) { //因为xls文件的头部也是D0CF11E0,所以需要判断文件后缀 return "xls"; } else { return "unknown"; } } catch ( IOException e) { e.printStackTrace(); return "unknown"; } } private static String bytesToHex(byte[] bytes) { StringBuilder hex = new StringBuilder(); for (byte b : bytes) { hex.append(String.format("%02X", b)); } return hex.toString(); } /** * 合并word文档 * * @param source 源文件 * @param target 目标文件 * @return */ public static File mergeFile(File source, File target) throws Exception { return MergeWordDocuments.mergeFile(source, target); } public static File toDocx(File file) { if (!AsposeUtil.getLicense(2)) { return file; } String docxName = UUID.randomUUID().toString() + ".docx"; File docxFile = new File(file.getParent() + File.separator + docxName); String tempDir = Global.getSystemConfig("temp.dir", "./attachment/temp"); File tempFile = new File(tempDir + File.separator + docxName); try (FileInputStream is = new FileInputStream(file);) { Document document = new Document(is); document.save(tempFile.getAbsolutePath(), com.aspose.words.SaveFormat.DOCX); return tempFile; } catch (Exception e) { e.printStackTrace(); } return docxFile; } public static File toDoc(File file) { if (!AsposeUtil.getLicense(2)) { return file; } String docxName = UUID.randomUUID().toString() + ".doc"; File docxFile = new File(file.getParent() + File.separator + docxName); String tempDir = Global.getSystemConfig("temp.dir", "./attachment/temp"); File tempFile = new File(tempDir + File.separator + docxName); try { Document document = new Document(new FileInputStream(file)); document.save(tempFile.getAbsolutePath(), SaveFormat.DOC); return tempFile; } catch (Exception e) { e.printStackTrace(); } return docxFile; } /** * 批量打包 * * @param pathList 文件路径集合 * @param os 输出流 * @return zip文件保存绝对路径 */ public static long createZip(List> pathList, OutputStream os) { try { long size = 0; ZipOutputStream out = new ZipOutputStream(os); String downloadPath; int symbol; Map fileNameCountMap = Maps.newHashMap(); int showCount = 0; String fileName; String head; String tail; for (Map pathMap : pathList) { downloadPath = pathMap.get(CmnConst.SOURCE_PATH); symbol = "1".equals(pathMap.get(CmnConst.ENCRPT_SIGN)) ? -1 : 0; //获得文件名 fileName = pathMap.get(CmnConst.REAL_FILE_NAME); head = fileName.substring(0, fileName.lastIndexOf(".")); tail = fileName.substring(fileName.lastIndexOf(".") + 1); showCount = fileNameCountMap.get(fileName) == null ? 0 : fileNameCountMap.get(fileName); if (showCount > 0) { fileName = head + "(" + showCount + ")." + tail; } fileNameCountMap.put(fileName, ++showCount); //以论文标题为每个文件命名 FileInputStream fis = new FileInputStream(downloadPath); out.putNextEntry(new ZipEntry(fileName)); //写入压缩包 int len; byte[] buffer = new byte[1024]; while ((len = fis.read(buffer)) > 0) { if (symbol == 1) { // 加密 out.write(encryption(buffer), 0, len); } else if (symbol == -1) { // 解密 out.write(decryption(buffer), 0, len); } else { // 单纯的复制 out.write(buffer, 0, len); } size += len; } out.closeEntry(); fis.close(); } out.close(); out.flush(); return size; } catch (Exception e) { throw new BaseException(FileCode.LOAD_FTP_PROPERTIES_FAIL.getValue(), FileCode.LOAD_FTP_PROPERTIES_FAIL.getText(), e); } } /** * 拷贝文件 * * @param sourceFile * @param aimPath * @param symbol 1:加密,-1:解密,0:不动 */ public static File copyFile(File sourceFile, String aimPath, int symbol) { if (StringUtils.isEmpty(aimPath)) { throw new BaseException(FileCode.INVALID_FILE_PATH.getValue(), FileCode.INVALID_FILE_PATH.getText()); } File aimFile = new File(aimPath); File aimDir = aimFile.getParentFile(); if (!aimDir.exists()) { aimDir.mkdirs(); } try (InputStream is = new FileInputStream(sourceFile); OutputStream os = new FileOutputStream(aimFile);) { int len; byte[] b = new byte[1024]; while ((len = is.read(b)) > 0) { if (symbol == 1) { // 加密 os.write(encryption(b), 0, len); } else if (symbol == -1) { // 解密 os.write(decryption(b), 0, len); } else { // 单纯的复制 os.write(b, 0, len); } } os.flush(); return aimFile; } catch (IOException e) { throw new BaseException(FileCode.COPY_FILE_FAIL.getValue(), FileCode.COPY_FILE_FAIL.getText(), e); } } public static void copyFile(File sourceFile, String aimPath) { copyFile(sourceFile, aimPath, 0); } /** * 加密 * * @param bytes * @return */ public static byte[] encryption(byte[] bytes) { /** * 设置一个加密算法,要求可逆,还可以通过解密得到原来的东西 * 我们这样做:每一个字节的值,都加上它的索引号 * 然后,交换第一个字节和最后一个字节的位置,即加密结束 */ for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) (bytes[i] + i); } byte temp = bytes[0]; bytes[0] = bytes[bytes.length - 1]; bytes[bytes.length - 1] = temp; return bytes; } /** * 解密 * * @param bytes * @return */ public static byte[] decryption(byte[] bytes) { /** * 解密算法,是加密的逆过程 * 先交换第一个字节和最后一个字节的位置 * 然后,每一个字节的值,都减去它的索引号 */ byte temp = bytes[0]; bytes[0] = bytes[bytes.length - 1]; bytes[bytes.length - 1] = temp; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) (bytes[i] - i); } return bytes; } }