fix: 金蝶与前端展示统一特批附件名为付款特批流程附件.pdf

resolveHcsFileName 改为统一业务名+扩展名(扩展名仍取C103-5响应头Content-Disposition后缀,其次Content-Type映射,兜底.pdf),不再上送合规侧原始名(文档内容.pdf);名称收敛为常量 PAYMENT_SPEC_ATTACH_NAME 供金蝶上送与前端展示行共用
This commit is contained in:
刘泉佳
2026-10-27 19:19:07 +08:00
parent a4fa6e4571
commit bdb1d3e4bb
3 changed files with 27 additions and 12 deletions
@@ -195,6 +195,11 @@ public final class HcsSyncConstant {
*/
public static final String PAYMENT_ATTACH_TYPE_SPEC_RESULT = "spec_result";
/**
* 合规特批结果附件统一业务名(金蝶上送与前端展示用,上传时按 C103-5 响应头补扩展名)
*/
public static final String PAYMENT_SPEC_ATTACH_NAME = "付款特批流程附件";
/**
* 附件类型:用印附件(双章归档文件,取值沿用 ContractManageServiceImpl#FILE_TYPE_SEAL_ARCHIVE)
*/
@@ -606,11 +606,11 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
rows.removeIf(row -> row instanceof Map<?, ?> map
&& HcsSyncConstant.PAYMENT_ATTACH_TYPE_SPEC_RESULT.equals(map.get("attachmentType")));
Map<String, Object> specRow = new LinkedHashMap<>();
specRow.put("name", "付款特批附件.pdf");
specRow.put("name", HcsSyncConstant.PAYMENT_SPEC_ATTACH_NAME + ".pdf");
specRow.put("attachmentType", HcsSyncConstant.PAYMENT_ATTACH_TYPE_SPEC_RESULT);
// 网关按服务名前缀路由(口径同 nacos skip-url);inline 内嵌预览 pdf,浏览器可直接查看/另存
specRow.put("url", "/blade-transport/hcs/attachment/download?fdId=" + vo.getHcsSpecAttachFdId()
+ "&inline=true&name=" + URLEncoder.encode("付款特批附件.pdf", StandardCharsets.UTF_8));
+ "&inline=true&name=" + URLEncoder.encode(HcsSyncConstant.PAYMENT_SPEC_ATTACH_NAME + ".pdf", StandardCharsets.UTF_8));
rows.add(specRow);
vo.setAttachmentsJson(JsonUtil.toJson(rows));
} catch (Exception exception) {
@@ -636,7 +636,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
kingdeeAttachmentSyncSupport.parseUserAttachments(entity.getAttachmentsJson()));
// 合规付款特批结果附件(paymentLegal/result 回传):C103-5 按合规附件ID 下载后联带上传金蝶
if (Func.isNotBlank(entity.getHcsSpecAttachFdId())) {
items.add(KingdeeAttachmentSyncSupport.KingdeeAttachmentItem.hcsAttachment("付款特批附件", entity.getHcsSpecAttachFdId()));
items.add(KingdeeAttachmentSyncSupport.KingdeeAttachmentItem.hcsAttachment(
HcsSyncConstant.PAYMENT_SPEC_ATTACH_NAME, entity.getHcsSpecAttachFdId()));
}
kingdeeAttachmentSyncSupport.syncAttachments(KingdeeAttachmentConstant.BIZ_PAY_APPLICATION,
id, entity.getKingdeeBillId(), items);
@@ -35,6 +35,7 @@ import org.springblade.core.tool.utils.Func;
import org.springblade.thirdparty.bfi.pojo.vo.BfiAttachmentUploadVO;
import org.springblade.thirdparty.bfi.service.IBfiService;
import org.springblade.transport.constant.KingdeeAttachmentConstant;
import org.springblade.transport.constant.HcsSyncConstant;
import org.springblade.transport.mapper.KingdeeAttachmentSyncMapper;
import org.springblade.transport.pojo.entity.KingdeeAttachmentSync;
import org.springblade.transport.support.hcs.HcsAttachmentSupport;
@@ -432,23 +433,31 @@ public class KingdeeAttachmentSyncSupport {
}
/**
* 解析合规附件文件名(BFI 附件上传要求带后缀名):名称已带后缀原样返回;
* 否则优先取 C103-5 响应头 Content-Disposition 文件名,其次按 Content-Type 映射扩展名追加,兜底 .pdf
* 解析合规附件文件名:统一业务名(HcsSyncConstant.PAYMENT_SPEC_ATTACH_NAME)+ 扩展名,
* 扩展名优先取 C103-5 响应头 Content-Disposition 文件名后缀,其次按 Content-Type 映射,兜底 .pdf;
* 不上送合规侧原始名(如"文档内容.pdf"),避免金蝶侧附件不可辨识
*
* @param response C103-5 文件流响应
* @param fallbackName 兜底名称(无扩展名)
* @return 带后缀名的文件名
* @param fallbackName 统一业务名
* @return 业务名 + 后缀名
*/
private String resolveHcsFileName(Response response, String fallbackName) {
String name = Func.isBlank(fallbackName) ? "付款特批附件" : fallbackName.trim();
String name = Func.isBlank(fallbackName) ? HcsSyncConstant.PAYMENT_SPEC_ATTACH_NAME : fallbackName.trim();
if (name.lastIndexOf('.') > 0) {
return name;
}
String fromDisposition = fileNameFromDisposition(firstHeader(response, "Content-Disposition"));
if (Func.isNotBlank(fromDisposition) && fromDisposition.lastIndexOf('.') > 0) {
return fromDisposition;
String extension = extensionOf(fileNameFromDisposition(firstHeader(response, "Content-Disposition")));
if (Func.isBlank(extension)) {
extension = extensionOfContentType(firstHeader(response, "Content-Type"));
}
return name + extensionOfContentType(firstHeader(response, "Content-Type"));
return name + extension;
}
/** 取文件名扩展名(含点,无扩展名返回空串) */
private String extensionOf(String fileName) {
String name = Func.isBlank(fileName) ? "" : fileName.trim();
int index = name.lastIndexOf('.');
return index > 0 && index < name.length() - 1 ? name.substring(index) : "";
}
/**