附件二开常见问题汇总
# 1. 如何获取附件或图片的文件流?
答:请调用如下接口(请遵守参数规范),返回值即为附件或图片的文件流。
## 1.1 缓存服务器的附件,获取文件流方式
返回值即为临时附件的文件流。
```java
//临时文件path适用
InputStream in = CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(String path);
```
参数规范1:**path必须为附件的临时路径**,示例:https://feature.kingdee.com:1026/feature_sit/tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1722520531024072704
参数规范2:**参数中的path必须在缓存中存在**(检查方法:直接访问这个链接,能下载即说明缓存中存在这个附件。),否则会返回空文件流,进而导致一系列二开问题。
## 1.2 文件服务器的附件,获取文件流方式
返回值即为持久化附件的文件流。
```java
//持久化附件path适用
InputStream in = FileServiceFactory.getAttachmentFileService().getInputStream(String path);
```
参数规范1:**path必须为附件的非加密相对路径**,示例:/tenant_devcore_dev/1402323749146986496/202305/1683569603244172288/5b3c272f9d5a42fdbecddf2d84bcdd56/Word文档.docx。(加密路径转换成明文路径的方法请见下文)
参数规范2:**参数中的path必须在文件服务器中存在**(检查方法,加上download前缀,直接访问这个链接,能下载即说明文件服务器中存在这个附件),否则会返回空文件流,进而导致一系列二开问题。
## 1.3 图片服务器的图片,获取文件流方式
返回值即为图片服务器中的图片的文件流。
```java
//图片服务器中的图片文件适用
InputStream in = FileServiceFactory.getImageFileService().getInputStream(String path);
```
参数规范1:**path必须为图片的非加密相对路径**,示例:/tenant_devcore_dev/1402323749146986496/202305/202305/yby_test/myattachment/images/DYaVqVPU1lX4bRzlGM/附件jpg测试图片.webp。(加密路径转换成明文路径的方法请见下文)
参数规范2:**参数中的path必须在图片服务器中存在**(检查方法,加上downloadImage前缀,直接访问这个链接,能下载即说明图片服务器中存在这个图片),否则会返回空文件流,进而导致一系列二开问题。
**注:**
**1. 附件download前缀和图片downloadImage前缀如何确认?**
方法1:F12调出控制台,然后在系统的任意页面刷新浏览器,找到getConfig.do请求,找到该请求的响应,响应中的attachmentserver参数的值即为附件的download前缀,fileserver为图片的downloadImage前缀。
![image-20230720104558212.webp](/download/0100c72f066b787d4c0c812625174d6f3e95.webp)
方法2:附件的download前缀,F12调出控制台,去单据任意下载一个附件,如图即为附件的download前缀。
![image-20230720105016163.webp](/download/01004568479533674edb88a0d30d1c0e8be8.webp)
图片的downloadImage前缀,F12调出控制台,去单据的**图片字段**任意上传一个图片,如图即为图片的downloadImage前缀。
![image-20230720105115797.webp](/download/010067bfbeee1a3144e39da32335b551bd6f.webp)
**2. 如果确认path已经在文件服务器或图片服务器中存在,但是在二开代码拿不到这个流,请在容器中执行curl命令访问该链接,检查是否能访问,如果不能访问,即说明容器的配置有问题。**
# 2. 如何通过附件的相对路径获取其全路径?
答:请调用如下接口(请遵守参数规范),返回值即为全路径url。
```java
//从文件服务器获取全路径
UrlService.getAttachmentFullUrl(String url);
//从图片服务器获取全路径
UrlService.getImageFullUrl(String url);
```
参数规范:**参数均为附件相对路径**,示例:/tenant_devcore_dev/1402323749146986496/202305/1683569603244172288/5b3c272f9d5a42fdbecddf2d84bcdd56/Word文档.docx。
# 3.如何获取临时文件url(将附件保存到==临时==文件服务器)?
答:请调用如下接口(请遵守参数规范)
## 3.1 获取临时附件相对地址
返回值为临时附件==相对==地址。(如:`tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1722520531024072704`)
```java
/**
* @description 将附件存到到临时文件服务器
* @param fileName 文件名
* @param InputStream 附件文件流
* @param timeout 文件过期时间(单位为秒)
* @return 临时附件url
*/
kd.bos.cache.TempFileCache#saveAsUrl(String filename, InputStream in, int timeout);
```
参数规范1:filename为文件名,示例:测试文档.pdf
参数规范2:in为文件流,传入前请确保文件流为正确的文件流,例如可以用in.available()获取文件流大小来判断
参数规范3:timeout为临时文件过期时间,单位为秒,示例:7200,标准产品过期时间为7200秒,即2小时。
## 3.1 获取临时附件绝对地址
返回值为临时附件==绝对==地址。(如`https://feature.kingdee.com:1026/feature_sit/tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1722520531024072704`)
```java
/**
* @description 将附件存到到临时文件服务器
* @param fileName 文件名
* @param InputStream 附件文件流
* @param timeout 临时文件过期时间(单位为秒)
* @return 临时附件url
*/
kd.bos.cache.TempFileCache#saveAsFullUrl(String filename, InputStream in, int timeout);
```
参数规范1:filename为文件名,示例:测试文档.pdf
参数规范2:in为文件流,传入前请确保文件流为正确的文件流,例如可以用in.available()获取文件流大小来判断
参数规范3:timeout为临时文件过期时间,单位为秒,示例:7200,标准产品过期时间为7200秒,即2小时。
# 4.如何获取持久化文件url(如何将附件保存到文件服务器)?
答:请调用如下接口(请遵守参数规范)
场景描述:单据中由二开绑定的附件,下载地址可能是一个临时下载链接,如果不将临时下载链接转换成持久化链接,绑定附件2小时过后,附件下载链接将会失效,导致无法下载。
## 4.1 附件面板适用
返回值即为持久化url。
```java
/**
* @description 把系统缓存中的临时附件上传到远程服务器
* @param tempUrl 缓存中临时附件url
* @param appId 应用编码
* @param formId 表单标识
* @param pkId 单据pkid
* @param fileName 文件名
* @param isDeleteTempFile 是否删除缓存中的临时文件
* @param createNewFileWhenExists 当文件存在时新建文件
* @return 文件相对于文件服务器的相对路径
*/
kd.bos.servicehelper.AttachmentServiceHelper#saveTempToFileService(String tempUrl, String appId, String formId, Object pkId, String fileName, boolean isDeleteTempFile, boolean createNewFileWhenExists)
```
参数规范1:tempUrl 为缓存中临时附件url,示例:https://feature.kingdee.com:1026/feature_sit/tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1722520531024072704
参数规范2:appId 为应用编码,示例:yby_test_app
参数规范3:formId 为表单标识,示例:yby_test_formId
参数规范4:pkId 为单据主键,示例:1723102865825785856
参数规范5:fileName 为文件名,示例:测试文档.pdf
参数规范6:isDeleteTempFile 代表是否设置是否删除缓存中的临时文件,示例:true 或 false
参数规范7:createNewFileWhenExists 代表是否设置当文件存在时新建文件,示例:true 或 false
## 4.2 附件字段适用
返回值即为持久化url。
```java
/**
* @description 把系统缓存中的临时附件上传到远程服务器
* @param tempUrl 缓存中临时附件url
* @param AttPk 附件id
* @param fileName 附件文件名
* @return 文件相对于文件服务器的相对路径
*/
kd.bos.servicehelper.attachment.AttachmentFieldServiceHelper#saveTempToFileService(String tempUrl, Object AttPk, String fileName)
```
参数规范1:tempUrl 为缓存中临时附件url,示例:https://feature.kingdee.com:1026/feature_sit/tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1722520531024072704
参数规范4:AttPk 为单据主键,示例:1723102865825785856
参数规范5: fileName 为文件名,示例:测试文档.pdf
# 5. 如何将附件绑定到单据上的附件字段或附件面板?
答:请参考文档 [附件绑定单据接口](https://vip.kingdee.com/article/126693402527067136?productLineId=29&isKnowledge=2)
# 6. 如何获取预览url?
答:请调用如下接口(请遵守参数规范)
## 6.1 获取临时文件预览url
返回值为临时文件预览url。
```java
/**
* 获取临时附件的预览url
*
* @param path 临时附件的downloadUrl全路径
* @return 临时附件的预览url
*
* 入参示例:http://localhost:8080/ierp/tempfile/download.do?
* configKey=redis.serversForCache&id=tempfile-1688297935936176128
*/
kd.bos.entity.datamodel.IAttachmentModel#getTempFilePreviewUrl(String path)
```
参数规范:path为临时附件的downloadUrl**绝对路径**,示例:`http://localhost:8080/ierp/tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1688297935936176128`
## 6.2 获取持久化文件预览url
返回值为持久化文件预览url。
```java
/**
* 获取持久化附件的预览url
*
* @param path 持久化附件的downloadUrl相对路径
* @return 持久化附件的预览url
*
* 入参示例:
/tenant_devcore_dev/1402323749146986496/202305/1683569603244172288/5b3c272f9d5a42fdbecddf2d84bcdd56/Wo rd文档.docx
*/
kd.bos.url.UrlService#getAttachmentPreviewUrl(String path)
```
参数规范:path为持久化附件的downloadUrl相对路径,示例:`/tenant_devcore_dev/1402323749146986496/202305/1683569603244172288/5b3c272f9d5a42fdbecddf2d84bcdd56/Wo rd文档.docx`
# 7.在文件服务器中附件的标准路径规则是什么?
## 7.1 附件面板标准路径规则
答:租户id/账户id/日期/应用编码/单据编码/单据主键/attachments/uuid/文件名
## 7.2 附件字段标准路径规则
答:租户id/账户id/日期/附件id/uuid/文件名
# 8.标准附件路径的各个层级分别代表什么?
答:附件字段和附件面板的标准附件路径不同,下面结合示例进行讲解。
## 8.1 附件面板
示例:`/tenant_devcore_dev/1402323749146986496/202304/kd_test_app/kd_test_bill/1641415906691197952/attachments/d0b288fae63e44aca6a3ff9a60f04017/test.txt`
`tenant_devcore_dev`:租户id
`1402323749146986496`:账套id/数据中心id
`202304`:年月
`kd_test_app`:应用标识
`kd_test_bill`:业务对象标识
`1641415906691197952`:单据内码
`attachments`:常量(固定为attachments)
`d0b288fae63e44aca6a3ff9a60f04017`:uuid
`test.txt`:文件名
## 8.2 附件字段
示例:`/tenant_devcore_dev/1402323749146986496/202205/1413819776135974912/c7db175fd32a42cfbc2ad3e907daca66/test.txt`
`tenant_devcore_dev`:租户id
`1402323749146986496`:账套id/数据中心id
`202205`:年月
`1413819776135974912`:附件id(附件字段详情表t_bd_attachment中附件对应的id)
`c7db175fd32a42cfbc2ad3e907daca66`:uuid
`test.txt`:文件名
# 9. 如何生成附件的标准路径?
答:请调用如下接口(请遵守参数规范)
## 9.1 附件面板
```java
/**
* 根据提供的参数生成附件存储在文件服务器的相对路径(用于附件面板)
* @param tenantId 租户id
* @param accountId 账户id
* @param appId 应用编码
* @param formId 单据编码
* @param pkId 单据主键
* @param filename 文件名
* @return 存入文件服务器的相对路径
*/
kd.bos.util.FileNameUtils#getAttachmentFileName(String tenantId,String accountId,String appId, String formId, Object pkId ,String filename)
```
参数规范1:tenantId 为租户id,示例:tenant_devcore_dev
参数规范2:accountId 为账户id,示例:1402323749146986496
参数规范3:appId 为应用编码,示例:kd_test_app
参数规范4:formId 为业务对象标识,示例:kd_test_bill
参数规范5:pkId为单据主键,示例:1641415906691197952
参数规范6:filename 为文件名,示例:test.txt
## 9.2 附件字段
```java
/**
* 根据提供的参数生成附件存储在文件服务器的相对路径(用于附件字段)
* @param tenantId 租户id
* @param accountId 账户id
* @param AttPk 附件id
* @param filename 文件名
* @return 存入文件服务器的相对路径
*/
kd.bos.util.FileNameUtils#getAttachmentFileName(String tenantId,String accountId,Object AttPk,String filename)
```
参数规范1:tenantId 为租户id,示例:tenant_devcore_dev
参数规范2:accountId 为账户id,示例:1402323749146986496
参数规范3:AttPk 为附件id,示例:1413819776135974912
参数规范4:filename 为文件名,示例:test.txt
# 10.附件和图片的加密路径和明文路径有什么区别与联系?
考虑到系统安全,附件的url在系统中默认是加密的。每一个加密路径对应着一个明文路径,明文路径即为该附件(或图片)在文件服务器(或图片服务器)上的路径。加密路径和明文路径的区别如下:
附件加密路径:`f5446a9fbe684fdd8e41556ef846c1ae`
附件明文路径:
`/tenant_devcore_dev/1402323749146986496/202305/1683569603244172288/5b3c272f9d5a42fdbecddf2d84bcdd56/Word文档.docx`
图片加密路径:`f57bcc8b47914b3387d9399dedfe257b.webp`
图片明文路径:
`/tenant_devcore_dev/1402323749146986496/202305/202305/yby_test/myattachment/images/DYaVqVPU1lX4bRzlGM/附件jpg测试图片.webp`
# 11. 如何通过加密路径去查明文路径?
## 11.1 附件加密路径
1)通过接口查询(请遵守参数规范)
附件加密路径可以调用`kd.bos.fileservice.extension.FileServiceExt#getRealPath`,转换成明文路径,代码示例如下。
```java
String encryptPath = "c402cc4809d84f2a9d88f98f550a7944";
path = FileServiceExtFactory.getAttachFileServiceExt().getRealPath(encryptPath);
```
参数规范:**encryptPath为附件加密路径**,示例:c402cc4809d84f2a9d88f98f550a7944。
2)数据库查询
附件加密路径与明文路径的映射关系存在t_bas_filepathmapping表中,ffileid代表附件的加密路径,fpath代表附件的明文路径。
## 11.2 图片加密路径
1)通过接口查询(请遵守参数规范)
图片加密路径可以调用`kd.bos.fileservice.extension.FileServiceExt#getRealPath`,转换成明文路径,代码示例如下。
```java
String encryptPath = "954042e18a274f7f8f9cccbea0094bde.webp";
String path = FileServiceExtFactory.getImageFileServiceExt().getRealPath(encryptPath);
```
参数规范:**encryptPath为图片加密路径**,示例:954042e18a274f7f8f9cccbea0094bde.webp。
2)数据库查询
附件加密路径与明文路径的映射关系存在t_bas_imagefilepathmapping表中,,ffileid代表附件的加密路径,fpath代表附件的明文路径。
# 12.如何自定义附件面板的按钮及修改按钮可见性?
答:请参考文档[《自定义附件面板的按钮及修改按钮可见性》](https://vip.kingdee.com/article/236196563457491968?productLineId=29&isKnowledge=2)。
# 13.如何控制附件面板按钮锁定性?
答:请参考文档[《附件面板和附件字段按钮可见性、锁定性控制说明》](https://vip.kingdee.com/article/447440450748881408 )。
# 14.单据中,如何以时分秒的格式显示附件上传的时间?
答:二开方案如下:
```java
public class TestPlugin extends AbstractFormPlugin {
//附件面板的标识
private static final String ATTACHMENTPanel = "attachmentpanel";
@Override
public void afterBindData(EventObject e) {
Map<String, Object> meta = new HashMap<>();
meta.put("attachdf", "datetime");
//更新控件的元数据
this.getView().updateControlMetadata(ATTACHMENTPanel, meta);
}
}
```
![01096df70359322446cc91642c8c98e81e6c.webp](/download/01008adc4a30d5d4468491f65e7f254b1f8d.webp)
# 15.如何通过二开取消附件上传?
答:请参考文档[《beforeUpload取消上传插件示例介绍》](https://vip.kingdee.com/article/447439699649393920)。
# 16.如何获取文件一次性下载链接?
```java
/**
* @param disposableUrlParam 参数对象
* @return 返回一次性下载链接
*/
kd.bos.servicehelper.AttachmentServiceHelper#genCustomAttachUrl(DisposableUrlParam disposableUrlParam) {
```
**DisposableUrlParam构造函数传参规范**
- **path:持久化文件相对路径,或临时文件全路径。**
- path为附件的**临时**路径时,路径格式示例:`https://feature.kingdee.com:1026/feature_sit/tempfile/download.do?configKey=redis.serversForCache&id=tempfile-1722520531024072704`。
- path为附件的**持久化**路径时,路径格式示例:`/tenant_devcore_dev/1402323749146986496/202305/1683569603244172288/5b3c272f9d5a42fdbecddf2d84bcdd56/Word文档.docx`。
- **entityNum:单据标识,如:"testBill"。**
- **pkId:单据的pkId。** 如果需要验特殊数据权限,需要传对应单据的pkid;**若不需要验特殊数据权限,pkid传0L即可**。
- **permItem:权限项编码。** permItem参数需要传在系统中已经预置的权限项的编码(在权限项列表能找到,说明已预置)。编码是指在表T_PERM_PERMITEM中的FID字段,权限项列表入口以及权限项编码查看方式如下图。
![20231205162607086.webp](/download/0100eccce810b3c34e01ae9efe2452ff05fe.webp)
![20231205162619317.webp](/download/01003776bda2858f47de9c512cb82ff6c266.webp)
# 17.附件下载如何二开设置自定义验权?
答:kd.bos.service.attachment.extend.permission.IFilePermissionExtension 二开实现此接口,然后配置mc参数file.permission.ext.impl.classname为实现类的全路径,分别重写dealPermissionParam、checkPermission方法实现。文件验权扩展接口逻辑:先走苍穹验权,苍穹验证通过,则通过,苍穹验证不通过,再走接口,接口验证通过则通过。
# 18.附件存于分录行上,自定义验权中如何获取分录信息?
答:实现IFilePermissionExtension接口之后会传递一个path参数到实现类的checkPermission方法,获取之后查询t_bd_attachment表,查询条件为furl=path,查询字段为主键fid,然后再通过这个fid查询t_bas_bill_file_mapping这个表,查询条件是fattpkid,billentrypkid字段为对应的分录id。
# 19.在5.0.005及之前的版本,二开修改按钮可见性不生效,如何处理?
答:5.0.005及之前的版本,由于前端代码存在bug,故修改无效,请提单通过私包或者升级的方式来处理。
# 20.新系统初始化时如何导入原系统的附件并绑定表单?
答:请参考文档[《第三方系统如何上传附件到苍穹已有单据的附件字段》](https://vip.kingdee.com/knowledge/specialDetail/294832938980257024?category=294833149400665344&id=594589694923631360&productLineId=29&lang=zh-CN)。
# 21.调用AttachmentServiceHelper.upload方法绑定附件信息时,url过长导致数据保存失败,如何解决?
答:因为传入了url的全路径,而数据库需要保存的参数是path,需要通过UrlUtil.getParam(url,"path")获取到对应的path参数,覆盖原url参数。
# 常见误区
## 1. AttachmentServiceHelper的upload方法
AttachmentServiceHelper.upload 方法。此方法的方法名虽然叫upload,但实际上的**作用只是将传入的附件信息存到附件面板详情表t_bas_attachment中,也就是将附件信息绑定到单据**,**没有将附件上传的文件服务器的功能**,为防止误用,此处特别指出。
```java
/**
* @description 保存附件数据到数据库,注意此方法没有将附件上传的文件服务器的功能
* @param formId 单据编码
* @param pkId 单据主键
* @param attachments 附件信息集合
*/
kd.bos.servicehelper.AttachmentServiceHelper#upload(String formId, Object pkId, String attachKey, List<Map<String, Object>> attachments)
```
附件二开常见问题汇总
# 1. 如何获取附件或图片的文件流?答:请调用如下接口(请遵守参数规范),返回值即为附件或图片的文件流。## 1.1 缓存服务器的附件,...
点击下载文档
上一篇:打印不清晰问题汇总下一篇:单据多个字段使用编码规则生成编号
本文2024-09-23 00:36:02发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-140508.html
您需要登录后才可以发表评论, 登录登录 或者 注册
最新文档
热门文章