diff --git a/uapbd/src/client/nccloud/web/uapbd/material/action/MaterialPlmDownloadAction.java b/uapbd/src/client/nccloud/web/uapbd/material/action/MaterialPlmDownloadAction.java index b6b0ba09..591b62b9 100644 --- a/uapbd/src/client/nccloud/web/uapbd/material/action/MaterialPlmDownloadAction.java +++ b/uapbd/src/client/nccloud/web/uapbd/material/action/MaterialPlmDownloadAction.java @@ -2,9 +2,11 @@ package nccloud.web.uapbd.material.action; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import nc.bs.dao.BaseDAO; import nc.bs.dao.DAOException; import nc.bs.logging.Log; import nc.bs.trade.business.HYSuperDMO; +import nc.jdbc.framework.processor.ColumnProcessor; import nc.vo.bd.defdoc.DefdocVO; import nc.vo.cmp.util.StringUtils; import nc.vo.ml.NCLangRes4VoTransl; @@ -26,9 +28,7 @@ import org.owasp.esapi.ESAPI; import java.io.*; import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -39,6 +39,7 @@ import java.util.zip.ZipOutputStream; * @date 2025/8/4 */ public class MaterialPlmDownloadAction implements ICommonAction { + private static final BaseDAO dao = new BaseDAO(); private static final String LOG_INFO_NAME = "dldzlog"; private static final Log logger = Log.getInstance(LOG_INFO_NAME); private String plmBaseUrl = ""; @@ -52,6 +53,7 @@ public class MaterialPlmDownloadAction implements ICommonAction { private String materialFileIdUrl = "/sipmweb/api/{rid}/relation/{t}/{id}/data"; // 下载文件 private String downlownUrl = "/sipmweb/web/download"; + private Map materialMap = new HashMap<>(); @Override public Object doAction(IRequest request) { @@ -97,54 +99,119 @@ public class MaterialPlmDownloadAction implements ICommonAction { plmUser = configParams.get("plmUser"); passwd = configParams.getOrDefault("passwd", ""); token = getToken(); - - // 无论单个还是多个物料,均打包为ZIP(原单个物料返回单文件,无法同时返回两类文件) - return processMultipleFiles(materialCodeArr); + // 去重物料编码 + Set materialCodeSet = new HashSet<>(Arrays.asList(materialCodeArr)); + getMaterialMapInfo(materialCodeSet); + // 无论单个还是多个物料,均打包为ZIP + return processMultipleFiles(materialCodeSet); } /** - * 处理多个文件并打包(同时包含SIPM1和SIPM2) + * 获取物料的名称 * - * @param materialCodeArr 物料编码数组 - * @return 打包后的zip文件WebFile对象 + * @param materialCodeSet + * @return + */ + private void getMaterialMapInfo(Set materialCodeSet) throws DAOException { + for (String code : materialCodeSet) { + String sql = "select name from bd_material where code = '" + code + "'"; + String materialName = (String) dao.executeQuery(sql, new ColumnProcessor("name")); + materialMap.put(code, materialName); + } + } + + /** + * 处理多个物料文件,为每个物料创建单独的压缩包,然后将所有压缩包打包成一个大压缩包 + * + * @param materialCodeSet 物料编码数组 + * @return 包含所有物料压缩包的WebFile对象 * @throws Exception 异常 */ - private WebFile processMultipleFiles(String[] materialCodeArr) throws Exception { - // 在内存中的 ZIP 输出流 - ByteArrayOutputStream zipOut = new ByteArrayOutputStream(); - ZipOutputStream zipStream = new ZipOutputStream(zipOut); - int successCount = 0; // 成功处理的文件数 + private WebFile processMultipleFiles(Set materialCodeSet) throws Exception { + // 创建总的ZIP输出流 + ByteArrayOutputStream mainZipOut = new ByteArrayOutputStream(); + ZipOutputStream mainZipStream = new ZipOutputStream(mainZipOut); + + int successCount = 0; // 成功处理的物料数 + try { - for (int i = 0; i < materialCodeArr.length; i++) { - String materialCode = materialCodeArr[i]; + for (String materialCode : materialCodeSet) { try { - // 同时处理当前物料的SIPM1和SIPM2 - boolean success1 = processSingleMaterialToZip(materialCode, i, "SIPM1", zipStream); - boolean success2 = processSingleMaterialToZip(materialCode, i, "SIPM2", zipStream); - if (success1) successCount++; - if (success2) successCount++; + // 为每个物料创建独立的压缩包 + WebFile singleMaterialZip = createSingleMaterialZip(materialCode); + if (singleMaterialZip != null) { + // 将单个物料的压缩包添加到总压缩包中 + mainZipStream.putNextEntry(new ZipEntry(singleMaterialZip.getFileName())); + byte[] buffer = new byte[1024]; + int bytesRead; + InputStream inputStream = singleMaterialZip.getInputStream(); + while ((bytesRead = inputStream.read(buffer)) != -1) { + mainZipStream.write(buffer, 0, bytesRead); + } + inputStream.close(); + mainZipStream.closeEntry(); + successCount++; + } } catch (BusinessException e) { logger.error("处理物料编码 " + materialCode + " 时出现异常: " + e.getMessage(), e); - // 继续处理下一个 + // 继续处理下一个物料 } } - zipStream.finish(); + + mainZipStream.finish(); } finally { - zipStream.close(); + mainZipStream.close(); } - // 如果没有任何文件成功处理 + // 如果没有任何物料成功处理 if (successCount == 0) { - throw new BusinessException("没有有效的文件可以打包"); + throw new BusinessException("没有有效的文件可下载"); } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); - String zipName = "图纸文档打包_" + sdf.format(new Date()); - // 创建 WebFile 对象用于 ZIP 文件 - InputStream ins = new ByteArrayInputStream(zipOut.toByteArray()); + String zipName = "物料文档打包_" + sdf.format(new Date()); + + // 创建返回的WebFile对象 + InputStream ins = new ByteArrayInputStream(mainZipOut.toByteArray()); return new WebFile(zipName + ".zip", ins); } + /** + * 为单个物料创建压缩包 + * + * @param materialCode 物料编码 + * @return 单个物料的压缩包WebFile对象 + * @throws Exception 异常 + */ + private WebFile createSingleMaterialZip(String materialCode) throws Exception { + // 创建单个物料的ZIP输出流 + ByteArrayOutputStream singleZipOut = new ByteArrayOutputStream(); + ZipOutputStream singleZipStream = new ZipOutputStream(singleZipOut); + + boolean hasFiles = false; + try { + // 处理SIPM1类型的文件(图纸) + boolean success1 = processSingleMaterialToZip(materialCode, 0, "SIPM1", singleZipStream); + // 处理SIPM2类型的文件(文件) + boolean success2 = processSingleMaterialToZip(materialCode, 0, "SIPM2", singleZipStream); + + hasFiles = success1 || success2; + + singleZipStream.finish(); + } finally { + singleZipStream.close(); + } + // 如果该物料没有任何文件,则返回null + if (!hasFiles) { + return null; + } + // 创建单个物料的压缩包文件名 + String fileName = materialCode + "_" + materialMap.get(materialCode) + ".zip"; + // 创建WebFile对象 + InputStream ins = new ByteArrayInputStream(singleZipOut.toByteArray()); + return new WebFile(fileName, ins); + } + /** * 将单个物料文件添加到ZIP流中 * @@ -187,7 +254,7 @@ public class MaterialPlmDownloadAction implements ICommonAction { } // 生成带类型标识的文件名,避免重复 - String fname = name + "_" + materialCode + "_" + getTypeName(fileType) + "_" + (index + i) + "." + suffix; + String fname = materialCode + "_" + materialMap.get(materialCode) + "_" + name + "_" + (index + i) + "." + suffix; zipStream.putNextEntry(new ZipEntry(fname)); zipStream.write(fileBytes); zipStream.closeEntry(); @@ -201,13 +268,15 @@ public class MaterialPlmDownloadAction implements ICommonAction { private String getToken() throws IOException, BusinessException { Map tokenMap = new HashMap<>(); tokenMap.put("uname", plmUser); - if (!"passwd".equals(passwd) && !"null".equals(passwd) && !"~".equals(passwd)) { - tokenMap.put("passwd", passwd); - } + tokenMap.put("passwd", passwd); tokenMap.put("f", "true"); String tokenStr = doGet(plmBaseUrl + tokenUrl, tokenMap); JSONObject jsonObject = JSONObject.parseObject(tokenStr); String token = jsonObject.getString("errmsg"); + if (!"0".equals(jsonObject.get("errcode") + "")) { + // 抛出错误信息 + throw new BusinessException(token); + } if (token == null || token.isEmpty()) { throw new BusinessException("PLM鉴权失败"); } @@ -300,8 +369,7 @@ public class MaterialPlmDownloadAction implements ICommonAction { .setSocketTimeout(200000) // 等待响应超时 .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build(); - CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm) - .setDefaultRequestConfig(globalConfig).build(); + CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(globalConfig).build(); String url = buildUrlWithParams(requestUrl, paramMap); HttpGet get = new HttpGet(url); String responseString = httpClient.execute(get, response -> EntityUtils.toString(response.getEntity())); @@ -325,8 +393,7 @@ public class MaterialPlmDownloadAction implements ICommonAction { .setSocketTimeout(200000) // 等待响应超时 .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build(); - CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm) - .setDefaultRequestConfig(globalConfig).build(); + CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(globalConfig).build(); String url = buildUrlWithParams(requestUrl, paramMap); HttpGet get = new HttpGet(url); byte[] responseString = httpClient.execute(get, response -> EntityUtils.toByteArray(response.getEntity()));