许鹏程
2025-05-19 c356c77683d055f82a668c28db8b56f9c5e04b84
src/main/java/com/product/file/service/FileManagerService.java
@@ -1,9 +1,11 @@
package com.product.file.service;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.product.common.lang.StringUtils;
import com.product.core.config.CoreConst;
import com.product.core.config.Global;
import com.product.core.connection.ConnectionManager;
import com.product.core.dao.BaseDao;
@@ -16,17 +18,16 @@
import com.product.core.spring.context.SpringMVCContextHolder;
import com.product.file.config.CmnConst;
import com.product.file.config.FileCode;
import com.product.file.util.AsposeUtil;
import com.product.file.util.CreateDocumentIndexThread;
import com.product.file.util.FileUtil;
import com.product.file.util.FileUtils;
import com.product.module.sys.entity.SystemUser;
import com.product.util.BaseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@@ -232,6 +233,39 @@
      return baseDao.executeUpdate(sql.toString());
   }
   /**
    * 根据附件uuid判断文件是否存在
    *
    * @param uuid
    * @return
    */
   public boolean fileExist(String uuid) {
      if (StringUtils.isEmpty(uuid)) {
         return false;
      }
      FieldSetEntity attachmentFse = baseDao.getFieldSetEntity(CmnConst.PRODUCT_SYS_ATTACHMENTS, uuid, false);
      if (attachmentFse == null) {
         return false;
      }
      //判断文件存放在服务器还是本地
      boolean needDownloadFromServerFlag = "1".equals(attachmentFse.getString(CmnConst.UPLOAD_SIGN));
      String dir = attachmentFse.getString(CmnConst.ATTACHMENT_URL);
      String fileName = attachmentFse.getString(CmnConst.ATTACHMENT_TITLE);
      boolean encrptSignFlag = "1".equals(attachmentFse.getString(CmnConst.ENCRPT_SIGN));
      if (needDownloadFromServerFlag) {
         // 需要从附件服务器上取文件
         FTPService ftpService = new FTPService();
         return ftpService.fileIsExist(dir, fileName);
      } else {
         // 直接在本地的目录中找文件
         String localBasePath = Global.getSystemConfig("local.dir", "");
         String path = localBasePath + File.separator + dir + File.separator + fileName;
         File file = new File(path);
         return file.isFile();
      }
   }
   /**
    * 上传文件到本地服务器
@@ -286,7 +320,7 @@
      String uuids = "";
      for (Map.Entry<Object, Object> entry : map.entrySet()) {
         fieldFse = fieldMetaEntity.getFieldMeta(fieldName);
         if (fieldFse == null || !CmnConst.ATTACHMENT_TYPE.equals(fieldFse.getString(CmnConst.FIELD_TYPE))) {
         if (fieldFse == null || (!CmnConst.ATTACHMENT_TYPE.equals(fieldFse.getString(CmnConst.FIELD_TYPE)) && !"file-image".equals(fieldFse.getString(CmnConst.FIELD_TYPE)))) {
            fse.setValue(entry.getKey().toString(), null);
            continue;
         }
@@ -386,6 +420,174 @@
   }
   /**
    *    根据附件表数据生成文档索引
    */
   public void readAttachmentCreateIndex() {
      // 遍历附件表
      DataTableEntity dtAttachment = baseDao.listTable(CmnConst.PRODUCT_SYS_ATTACHMENTS);
      if (BaseUtil.dataTableIsEmpty(dtAttachment)) {
         return;
      }
      for (int i = 0; i < dtAttachment.getRows(); i++) {
         // 获取附件信息,并判断是否有表和字段
         FieldSetEntity fseAttachment = dtAttachment.getFieldSetEntity(i);
         if (BaseUtil.strIsNull(fseAttachment.getString("attachment_data_field")) || BaseUtil.strIsNull(fseAttachment.getString("attachment_data_field"))) {
            continue;
         }
         // 查询原数据,有原数据再生成文档检索
         FieldSetEntity fseRecord = baseDao.getFieldSetEntityByFilter(fseAttachment.getString("attachment_data_table"), fseAttachment.getString("attachment_data_field") + " LIKE ?", new Object[]{"%" + fseAttachment.getUUID() + "%"}, false);
         if (fseRecord != null) {
            // 生成文档检索信息
            FieldSetEntity fseIndex = new FieldSetEntity();
            fseIndex.setTableName("fseIndex");
            fseIndex.setValue("function_uuid", fseAttachment.getString("function_uuid"));
            fseIndex.setValue("attachment_uuid", fseAttachment.getUUID());
            CreateDocumentIndexThread.getInstance().appendAttaInfo(fseIndex);
         }
      }
   }
   /**
    * 移动端升级,安装包下载
    *
    * @param fse
    * @param response
    */
   public void getFileContent(FieldSetEntity fse, HttpServletResponse response, boolean isUpgrade) throws IOException {
      if (isUpgrade) {
         FieldSetEntity attachmentFse = baseDao.getFieldSetEntity(CmnConst.PRODUCT_SYS_ATTACHMENTS, fse.getUUID(), false);
         if (attachmentFse == null || !"product_sys_app_version".equals(attachmentFse.getString("attachment_data_table"))) {
            return;
         }
         logger.info("正在获取文件流...");
         boolean needDownloadFromServerFlag = "1".equals(attachmentFse.getString(CmnConst.UPLOAD_SIGN));
         String dir = attachmentFse.getString(CmnConst.ATTACHMENT_URL);
         String fileName = attachmentFse.getString(CmnConst.ATTACHMENT_TITLE);
         //真实文件名
         String realFileName = attachmentFse.getString(CmnConst.FILE_NAME);
         String viewOnlineSign = attachmentFse.getString(CmnConst.VIEW_ONLINE_SIGN);
         boolean encrptSignFlag = "1".equals(attachmentFse.getString(CmnConst.ENCRPT_SIGN));
         boolean needOnlineViewFlag = "1".equals(fse.getString(CmnConst.NEED_ONLINE_VIEW)) && "1".equals(viewOnlineSign);
         String clientType = CoreConst.CLIENT_TYPE_APP;
         String contentType = "multipart/form-data";
         boolean isExcel = realFileName.endsWith(".xlsx") || realFileName.endsWith(".xls");
         if (needOnlineViewFlag) {
            //特殊处理: 如果客户端不是App 但预览的文件是Excel 直接返回excel源文件 content头标识是excel cheng 2025年2月11日10:41:41
            if (isExcel && !CoreConst.CLIENT_TYPE_APP.equals(clientType)) {
               contentType = "application/vnd.ms-excel";
            } else {
               dir += File.separator + CmnConst.TRANSFER_DIR_NAME;
            }
         }
         String path = dir + File.separator + fileName;
         if (needDownloadFromServerFlag) {
            // 需要从附件服务器上取文件
            FTPService ftpService = new FTPService();
            logger.info("需要从附件服务器上取文件...");
            response.setHeader("Access-Control-Expose-Headers", "*");
            response.setContentType(contentType);
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFileName, "UTF-8"));
            //设置头中的文件类型
            if (!needOnlineViewFlag && !encrptSignFlag) {
               logger.info("不需要解密且获取原文件...");
               try (ServletOutputStream os = response.getOutputStream()) {
                  ftpService.downloadFile(path, os);
               }
            } else {
               logger.info("需要解密或者获取转换后的文件...");
               String localTempPath = Global.getSystemConfig("temp.dir", "") + File.separator + fileName;
               File localTempFile = new File(localTempPath);
               OutputStream tempOs = new FileOutputStream(localTempFile);
               ftpService.downloadFile(path, tempOs);
               tempOs.flush();
               tempOs.close();
               if (needOnlineViewFlag && localTempFile.length() == 0L) {
                  // 若是预览,但是转换后的文件不存在,那么重新执行转换操作
                  File sourceFile = fileUtils.getFile(true, attachmentFse.getString(CmnConst.ATTACHMENT_URL), fileName, encrptSignFlag);
                  File tempSourceFile = new File(sourceFile.getParentFile().getAbsolutePath() + File.separator + attachmentFse.getString(CmnConst.FILE_NAME));
                  sourceFile.renameTo(tempSourceFile);
                  FileUtils.convertPdf(false, true, encrptSignFlag, true, tempSourceFile, dir, fileName, attachmentFse.getString(CmnConst.FILE_NAME));
                  tempSourceFile.delete();
                  // 重新拉文件
                  tempOs = new FileOutputStream(localTempFile);
                  ftpService = new FTPService();
                  ftpService.downloadFile(path, tempOs);
                  tempOs.flush();
                  tempOs.close();
               }
               response.setContentLengthLong(localTempFile.length());
               InputStream is = new FileInputStream(localTempFile);
               int len;
               byte[] b = new byte[1024];
               try (ServletOutputStream os = response.getOutputStream()) {
                  while ((len = is.read(b)) > 0) {
                     os.write(encrptSignFlag ? FileUtil.decryption(b) : b, 0, len);
                  }
                  os.flush();
                  is.close();
               }
               // 删除临时文件
               localTempFile.delete();
            }
         } else {
            // 直接在本地的目录中找文件
            logger.info("直接在本地的目录中找文件...");
            String localBasePath = Global.getSystemConfig("local.dir", "");
            path = localBasePath + File.separator + path;
            File file = new File(path);
            if (needOnlineViewFlag && file.exists() && CoreConst.CLIENT_TYPE_APP.equals(clientType)) {
               //特殊处理: 是App 但预览的文件是Excel 需要将之前已转换为的文件删除掉重新转换(因转换后的格式不是pdf)
               String changeTime = "2025-02-11 23:59:59";
               Date changeDate = DateUtil.parse(changeTime, "yyyy-MM-dd HH:mm:ss");
               long fileTime = file.lastModified();
               //如果时间是 2025年2月10日23:59:59,那么就重新转换
               //删除文件
               if (fileTime <= changeDate.getTime()) {
                  file.delete();
               }
            }
            if (needOnlineViewFlag && !file.exists()) {
               // 若是预览,但是转换后的文件不存在,那么重新执行转换操作
               File sourceFile = fileUtils.getFile(false, attachmentFse.getString(CmnConst.ATTACHMENT_URL), fileName, encrptSignFlag);
               File tempSourceFile = new File(sourceFile.getParentFile().getAbsolutePath() + File.separator + attachmentFse.getString(CmnConst.FILE_NAME));
               sourceFile.renameTo(tempSourceFile);
               FileUtils.convertPdf(false, false, encrptSignFlag, true, tempSourceFile, dir, fileName, attachmentFse.getString(CmnConst.FILE_NAME));
               tempSourceFile.delete();
            }
            int len;
            byte[] b = new byte[1024];
            InputStream is = new FileInputStream(file);
            response.setHeader("Access-Control-Expose-Headers", "*");
            response.setContentType(contentType);
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFileName, "UTF-8"));
            response.setContentLengthLong(file.length());
            try (ServletOutputStream os = response.getOutputStream()) {
               while ((len = is.read(b)) > 0) {
                  if (encrptSignFlag) {
                     // 需要解密
                     logger.info("需要解密...");
                     os.write(FileUtil.decryption(b), 0, len);
                  } else {
                     // 无需解密
                     os.write(b, 0, len);
                  }
               }
               os.flush();
            }
            is.close();
         }
         logger.info("文件流获取成功");
      }
   }
   /**
    * 提取文件信息-下载文件或者在线预览文件
    *
    * @param fse
@@ -406,9 +608,17 @@
      String viewOnlineSign = attachmentFse.getString(CmnConst.VIEW_ONLINE_SIGN);
      boolean encrptSignFlag = "1".equals(attachmentFse.getString(CmnConst.ENCRPT_SIGN));
      boolean needOnlineViewFlag = "1".equals(fse.getString(CmnConst.NEED_ONLINE_VIEW)) && "1".equals(viewOnlineSign);
      if (needOnlineViewFlag && !realFileName.endsWith(".xlsx") && !realFileName.endsWith(".xls")) {
         // 需要在线预览且转换之后才能在线预览 excel 文件不需要转换直接输出预览
         dir += File.separator + CmnConst.TRANSFER_DIR_NAME;
      String clientType = SpringMVCContextHolder.getCurrentUser().getClientType();
      String contentType = "multipart/form-data";
      boolean isExcel = realFileName.endsWith(".xlsx") || realFileName.endsWith(".xls");
      if (needOnlineViewFlag) {
         //特殊处理: 如果客户端不是App 但预览的文件是Excel 直接返回excel源文件 content头标识是excel cheng 2025年2月11日10:41:41
         if (isExcel && !CoreConst.CLIENT_TYPE_APP.equals(clientType)) {
            contentType = "application/vnd.ms-excel";
         } else {
            dir += File.separator + CmnConst.TRANSFER_DIR_NAME;
         }
      }
      String path = dir + File.separator + fileName;
@@ -417,11 +627,8 @@
         FTPService ftpService = new FTPService();
         logger.info("需要从附件服务器上取文件...");
         response.setHeader("Access-Control-Expose-Headers", "*");
         if (realFileName.endsWith(".xlsx") || realFileName.endsWith(".xls")) {
            response.setContentType("application/vnd.ms-excel");
         } else {
            response.setContentType("multipart/form-data");
         }
         response.setContentType(contentType);
         response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFileName, "UTF-8"));
         //设置头中的文件类型
         if (!needOnlineViewFlag && !encrptSignFlag) {
@@ -452,6 +659,19 @@
               tempOs.flush();
               tempOs.close();
            }
            boolean delete = false;
            if (realFileName.endsWith(".xls") && needOnlineViewFlag && localTempFile.exists() && !CoreConst.CLIENT_TYPE_APP.equals(clientType)) {
               //转换为xlsx
               AsposeUtil.xls2xlsx(localTempFile.getPath(), getSystemConfig("temp.dir", "/attachment/temp") + "/" + localTempFile.getName(), "xls");
               File oldFile = localTempFile;
               localTempFile = new File(getSystemConfig("temp.dir", "/attachment/temp") + "/" + localTempFile.getName());
               if (!localTempFile.isFile()) {
                  localTempFile = oldFile;
               } else {
                  delete = true;
                  oldFile.delete();
               }
            }
            response.setContentLengthLong(localTempFile.length());
            InputStream is = new FileInputStream(localTempFile);
            int len;
@@ -472,6 +692,17 @@
         String localBasePath = Global.getSystemConfig("local.dir", "");
         path = localBasePath + File.separator + path;
         File file = new File(path);
         if (needOnlineViewFlag && file.exists() && CoreConst.CLIENT_TYPE_APP.equals(clientType)) {
            //特殊处理: 是App 但预览的文件是Excel 需要将之前已转换为的文件删除掉重新转换(因转换后的格式不是pdf)
            String changeTime = "2025-02-11 23:59:59";
            Date changeDate = DateUtil.parse(changeTime, "yyyy-MM-dd HH:mm:ss");
            long fileTime = file.lastModified();
            //如果时间是 2025年2月10日23:59:59,那么就重新转换
            //删除文件
            if (fileTime <= changeDate.getTime()) {
               file.delete();
            }
         }
         if (needOnlineViewFlag && !file.exists()) {
            // 若是预览,但是转换后的文件不存在,那么重新执行转换操作
            File sourceFile = fileUtils.getFile(false, attachmentFse.getString(CmnConst.ATTACHMENT_URL), fileName, encrptSignFlag);
@@ -480,15 +711,24 @@
            FileUtils.convertPdf(false, false, encrptSignFlag, true, tempSourceFile, dir, fileName, attachmentFse.getString(CmnConst.FILE_NAME));
            tempSourceFile.delete();
         }
         boolean delete = false;
         if (realFileName.endsWith(".xls") && needOnlineViewFlag && file.exists() && !CoreConst.CLIENT_TYPE_APP.equals(clientType)) {
            //转换为xlsx
            AsposeUtil.xls2xlsx(file.getPath(), getSystemConfig("temp.dir", "/attachment/temp") + "/" + file.getName(), "xls");
            File oldFile = file;
            file = new File(getSystemConfig("temp.dir", "/attachment/temp") + "/" + file.getName());
            if (!file.isFile()) {
               file = oldFile;
            } else {
               delete = true;
            }
         }
         int len;
         byte[] b = new byte[1024];
         InputStream is = new FileInputStream(file);
         response.setHeader("Access-Control-Expose-Headers", "*");
         if (realFileName.endsWith(".xlsx") || realFileName.endsWith(".xls")) {
            response.setContentType("application/vnd.ms-excel");
         } else {
            response.setContentType("multipart/form-data");
         }
         response.setContentType(contentType);
         response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFileName, "UTF-8"));
         response.setContentLengthLong(file.length());
         try (ServletOutputStream os = response.getOutputStream()) {
@@ -504,7 +744,10 @@
            }
            os.flush();
         }
         is.close();
         if (delete) {
            file.delete();
         }
      }
      logger.info("文件流获取成功");
   }