您现在的位置是:首页 >技术交流 >360极速版无法下载压缩包附件的问题网站首页技术交流

360极速版无法下载压缩包附件的问题

cnd1551 2026-05-02 00:01:04
简介360极速版无法下载压缩包附件的问题

Java代码

/**
 * 根据合同ID批量下载合同附件
 */
@RequestMapping(value={"/downloadAttachmentByConIds.do"}, method = RequestMethod.POST)
public void downloadAttachmentByConIds(@RequestParam("urls") String urls, HttpServletResponse response) throws IOException {
    String contractIds =  java.net.URLDecoder.decode(urls,"UTF-8");
    String[] conIds = contractIds.split(",");
    if(conIds.length== 0) {
           try {
          response.setCharacterEncoding("UTF-8");
               response.getWriter().write("文件不存在");
           } catch (IOException e) {
               throw new RuntimeException(e);
           }
    }
    // 根据合同ID获取文件实体类
    List<AttachmentEntry> attachmentEntryList = attachService.getAttachmentList(conIds);

    // 通过合同ID获取合同实体列表
    List<ContractEntry> contractEntryList = contractService.getContractListByIds(Arrays.asList(conIds));
    // 键存放合同ID、值存放合同实体
    Map<String,ContractEntry> conMap = new HashMap<>();
    for(int k=0;k<contractEntryList.size();k++){
       conMap.put(contractEntryList.get(k).getPk(),contractEntryList.get(k));
    }
    // 服务端创建一个大的文件夹D:IDEAworkspaceJMIS-DHsrcmainwebapp/upload	emp
    String parentDirPathStr = WebAppUtil.getRealPath(File.separator + "upload" + File.separator + "temp" + File.separator);
    Path parentDirPathObj = Paths.get(parentDirPathStr);
    Files.createDirectories(parentDirPathObj);
    // 文件实体列表按照合同ID进行分组,并放入Map,键为合同ID,值为文件实体
    Map<String, List<AttachmentEntry>> stringAttachmentEntryMap = groupByAttribute(attachmentEntryList, "busiId", AttachmentEntry.class);
    // 遍历文件实体列表
    for(Map.Entry<String,List<AttachmentEntry>> entry : stringAttachmentEntryMap.entrySet()){
       // 该合同编号下的所有附件
       List<AttachmentEntry> singleAttachmentEntries = entry.getValue();
       // 该合同编号关联的合同实体
       ContractEntry contractEntry = conMap.get(entry.getKey());
       String conName = contractEntry.getName().trim();
       String conNo = contractEntry.getNo().trim();
       // 拼接小文件夹名称:合同编号+合同名称
       String childDirPathStr = conNo + "-" + conName;
       // 服务端创建一个小文件夹 D:IDEAworkspaceJMIS-DHsrcmainwebapp/upload	emp合同编号-合同名称
       Path childDirPathObj = parentDirPathObj.resolve(childDirPathStr);
       Files.createDirectories(childDirPathObj);
       // 将文件保存到对应的小文件夹
       for(AttachmentEntry file : singleAttachmentEntries){
          File documentFile = attachService.getDocumentFile(file);
           // 源路径 D:IDEAworkspaceJMIS-DHsrcmainwebapp/uploadcontract19347598962.doc
          Path filePath = childDirPathObj.resolve(documentFile.getPath());
           // 目标路径 D:IDEAworkspaceJMIS-DHsrcmainwebapp/upload	emp合同编号-合同名称文件名称.doc
          Path resolve = childDirPathObj.resolve(file.getName());
          // 源路径文件复制到目标路径
          Files.copy(filePath, resolve);
       }
    }

    // 3. 压缩大文件夹为 ZIP
    String zipName = "合同附件.zip";
    response.setContentType("application/zip");
    response.setHeader("Content-disposition", "attachment;filename=" + new String(zipName.getBytes("GBK"), "ISO-8859-1"));
    try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
       zipFolder(parentDirPathObj.toFile(), parentDirPathObj.getFileName().toString(), zipOut);
    }

    // 4. 删除临时文件夹
    deleteFolder(parentDirPathObj.toFile());
}



/**
 * 根据对象的指定属性进行分组。
 *
 * @param list           要分组的对象列表
 * @param attributeName  用于分组的属性名(假设对象有getter方法,如getXXX)
 * @param clazz          对象的类类型
 * @param <T>            对象的类型
 * @return 分组后的Map,键是属性值,值是具有该属性值的对象列表
 */
public static <T> Map<String, List<T>> groupByAttribute(List<T> list, String attributeName, Class<T> clazz) {
    Map<String, List<T>> groupedMap = new HashMap<>();
    try {
       // 通过反射获取getter方法,假设getter方法名为get+属性名首字母大写+剩余部分
       Method getter = clazz.getMethod("get" + Character.toUpperCase(attributeName.charAt(0)) + attributeName.substring(1));
       for (T obj : list) {
          String attributeValue = (String) getter.invoke(obj); // 调用getter方法获取属性值
          List<T> listForAttribute = groupedMap.get(attributeValue);
          if (listForAttribute == null) {
             listForAttribute = new ArrayList<>();
             groupedMap.put(attributeValue, listForAttribute);
          }
          listForAttribute.add(obj);
       }
    } catch (NoSuchMethodException | IllegalAccessException | java.lang.reflect.InvocationTargetException e) {
       e.printStackTrace();
       // 处理反射异常
    }
    return groupedMap;
}

/**
 * 递归压缩文件夹(保留目录结构)
 */
private void zipFolder(File folder, String parentPath, ZipOutputStream zipOut) throws IOException {
    for (File file : folder.listFiles()) {
       String entryName = parentPath + "/" + file.getName();
       if (file.isDirectory()) {
          zipFolder(file, entryName, zipOut); // 递归处理子文件夹
       } else {
          ZipEntry zipEntry = new ZipEntry(entryName);
          zipOut.putNextEntry(zipEntry);
          Files.copy(file.toPath(), zipOut);
          zipOut.closeEntry();
       }
    }
}

/**
 * 递归删除文件夹
 */
private void deleteFolder(File folder) {
    if (folder.isDirectory()) {
       for (File file : folder.listFiles()) {
          deleteFolder(file);
       }
    }
    folder.delete();
}

Ext.js代码


PlanContractList.AttachmentDownload = function(cGridList) {
    var selectionModel = cGridList.getSelectionModel();
    let downIds = [];
    if (selectionModel.hasSelection()) {
       var selections = selectionModel.getSelections();
        for(let k = 0;k<selections.length;k++){
            downIds[k] = selections[k].data.pk
        }
        var winHeight = window.document.documentElement.clientHeight-10;
        //doDownload('/contract/downloadAttachmentByConIds.do?contractIds=' + downIds.join(","));
            var formStr = '<form style="visibility:hidden;" method="POST" action="' + __ctxPath + '/contract/downloadAttachmentByConIds.do' + '">' +
                                '<input type="hidden" name="urls" value="' + encodeURIComponent(downIds.join(",")) + '" />' +
                           '</form>';
           var win = window.open("", "_blank", "height=" + winHeight
                                   + ",top=80,left=80,toolbar=no, menubar=no, scrollbars=yes, resizable=yes");
           win.document.body.innerHTML = formStr;
           win.document.forms[0].submit();
        } else {
          Ext.Msg.alert("提示信息:", "至少选中一条记录");
    }
};
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。