feat(material):优化物料PLM文件下载功能
- 增加物料编码去重逻辑,避免重复下载- 为每个物料生成独立压缩包,再统一打包成ZIP文件 - 新增物料名称查询功能,用于构建更清晰的文件名 - 优化文件命名规则,包含物料编码和名称信息 - 增强PLM接口鉴权错误处理机制
This commit is contained in:
		
							parent
							
								
									8503c03d6a
								
							
						
					
					
						commit
						20520fe986
					
				|  | @ -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<String, String> 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<String> 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<String> 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<String> 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<String, String> 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())); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue