feat(material):优化物料PLM文件下载功能

- 增加物料编码去重逻辑,避免重复下载- 为每个物料生成独立压缩包,再统一打包成ZIP文件
- 新增物料名称查询功能,用于构建更清晰的文件名
- 优化文件命名规则,包含物料编码和名称信息
- 增强PLM接口鉴权错误处理机制
This commit is contained in:
mzr 2025-10-13 11:45:19 +08:00
parent 8503c03d6a
commit 20520fe986
1 changed files with 104 additions and 37 deletions

View File

@ -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()));