# JSP附件组件
# 前言
附件上传下载组件,是在JSP开发规范基础上实现的前后端附件互通的模块组件,只要按照JSP开发规范,正确引入common_header.jsp、common_footer.jsp,则可以调用本组件。
# 应用范围
协同、公文等模块附件区文件的渲染及上传操作。
文档管理/知识管理应用的用户上载文件的管理
# 附件管理
附件组件的使用分为前端和后端,两部分配合使用才能实现完整的附件相关功能。在开发时需要分别编写JSP前端、Java后端代码。
- 前端负责界面展现
- 后端负责附件的保存、获取相关逻辑
附件上传分为下面几种方式:
标准方式:即附件的显示、保存等功能不需要调用者关系,组件会完成所有功能。调用者只按要求调用几个接口即可。使用方法参考下面3.2.1
扩展方式:即组件只完成部分功能,剩余功能需要调用者来处理。适用于上传、解析后不在使用该文件。即上传后对该文件直接解析处理,并不返回调用页,在调用者处理完后返回自己期望的页面。
一页多个上传组件:即一个页面做多处需要上传文件,每处上传的属性和显示的位置不同。标准方式和扩展方式都支持。
js动态创建方式:上面三种都依赖与页面完整加载,对于页面不重新加载,而是通过js操作的需使用此方式。例如行为动态生成,每行都包含一个上传组件,需要通过js方法动态生成。
# 附件上传-标准方式
(1)编写前端代码:
1、声明一个附件上传组件;
2、在对应的菜单或者按钮上调用 insertAttachment() 方法
3、在自己的页面中submit form时必须使用分区方式提交。
<!-- 附件上传组件区域start -->
<div id="attachmentTR" style="display:none;">${ctp:i18n("common.attachment.label")}:(<span id="attachmentNumberDiv"></span>)</div>
<div class="comp" comp="type:'fileupload',applicationCategory:'1',canDeleteOriginalAtts:false,originalAttsNeedClone:false" attsdata='${attachmentsJSON}'>
<!-- 附件上传组件区域end -->
<!-- 定义触发按钮,点击触发附件上传start -->
<input type="button" onclick="insertAttachment()" value="上传附件">
<!-- 定义触发按钮,点击触发附件上传end -->
div id="attachmentTR"
是显示附件数量区域,如果要显示附件数量,请在需要显示附件数量的位置放置。样式可以改,里面的id都不能修改。- comp属性值为:
type:'fileupload'
,表示附件组件。 - 如果一个页面只有一个上传组件,则可以使用insertAttachment()执行上传,如果一个页面有多个上传组件则需要调用insertAttachmentPoi(attachmentTrId属性的值)方法,该方法需要和attachmentTrId属性配合使用。
- insertAttachment()是平台内置方法,执行此函数则进行上传,不用开发自己封装函数。
上传附件组件comp支持如下属性:
属性 | 说明 | 实例 |
---|---|---|
type | 指当前为上传文件组件,值为固定值 | type:'fileupload |
attsdata | 指原有已上传的附件,需要把原有的附件显示出来。 这个属性对应的值来自于Controller,从后端参考标准接口获取附件对象字符串,参考示例 | |
applicationCategory | 应用分类,统一在ApplicationCategoryEnum定义 | applicationCategory:'1' |
canDeleteOriginalAtts | 指能否删除原有的附件,如转发协同不能删除原有附件 | canDeleteOriginalAtts:false |
originalAttsNeedClone | 是否需要复制原有附件,常用在模板调用 | originalAttsNeedClone:false |
extensions | 允许上传的文件类型,用文件会后缀表示,多个类型用逗号分隔(,) | extensions:'txt,jpg' |
maxSize | 上传文件的大小限制,单位为字节 | maxSize:10240000 |
isEncrypt | 对上传的文件是否加密,true为加密;false为不加密 | isEncrypt:false |
quantity | 最多上传文件个数,不使用该参数事默认是5 | quantity:1 |
attachmentTrId | 一页支持多个附件上传组件时使用,和insertAttachmentPoi('poi77')方法配合使用 在方法中传入该属性的值。 | attachmentTrId:poi77 |
callMethod | 在不改变使用过程的情况下,在上传附件后回调该方法。 此属性依赖takeOver属性,takeOver值为false 注意!方法名必须用引号括起来作为字符串。具体返回值请参考扩展方式中的说明。 | callMethod:'testCallBack' takeOver:false |
takeOver | 是否接管附件上传(即弹出窗口关闭)之后的逻辑。 该属性和callMethod配合使用,如果不使用回调方法,可以不使用该属性; 否则属性值应为false | takeOver:false |
showReplaceOrAppend | 是否显示“追加”、“覆盖”radio。即,在上传页面中会提供如下元素, 业务模块根据下面元素确定相关逻辑。 | showReplaceOrAppend:true |
firstSave | 是否先保存附件表信息,ture为先保存,false或者无该属性为后保存。 并且为ture时,回调方法得到的参数值为包含Attachment 的js 数组,否则为逗号(,)分隔的文件ID字符串。 这种情况下后端应该调用附件更新接口,目的是关联业务数据域附件数据。 | firstSave:true |
(2)后端上传附件代码逻辑:
后端负责对附件信息的存储,其实如果前端JSP编写的是标准的附件组件,则后端附件存储是不需要业务组自己写代码。
在触发前端insertAttachment()执行上传附件操作时,附件组件就会自动自动调用后台的AttachmentManager#create接口来实现附件的上传,接口参数定义如下:
/**
* 该方法必须和 comp=type:'fileupload' 配合使用
* @param category 所属应用分类
* @param reference 主题Id,如协同的Id
* @param subReference 二级主题Id,如协同的回复Id,如果当前是给协同上传附件,则该subReference 与 reference相同
* @return 附件类型任意组合 如:"012"、"12"、"01"、"02"; 其中 0-文件附件 1-图片 2-关联文 ,排列无序
* @see com.seeyon.ctp.common.filemanager.Constants.ATTACHMENT_TYPE_FILE
* @see com.seeyon.v3x.common.filemanager.Constants.isUploadLocaleFile(String)
* @throws Exception
*/
public String create(ApplicationCategoryEnum category, Long reference, Long subReference) throws Exception;
(3)attsdata后端返回已上传附件列表
前端编写代码comp组件中attsdata='${attachmentsJSON}
用于进入JSP页面时,返回并显示已经上传过的附件列表,EL表达式${attachmentsJSON}
数据来自于后端,此附件列表数据需要编写在MVC层的Controller层,在重定向到当前JSP页面前准备好数据。
ModelAndView modelAndView = new ModelAndView("apps/file/inituploadfile");
// attachmentManager#getAttListJSON(主数据Id)可以组装attsdata数据
modelAndView.addObject("attachmentsJSON", attachmentManager.getAttListJSON(dataId));
return modelAndView;
# 附件上传-扩展方式
扩展方式除了由平台完成附件的上传外,还支持前端自定义回调函数:在平台上传附件成功之后将结果返回给回调函数,方便业务组拿到数据做自己的后续逻辑开发。
如下场景:产品支持上传excel格式的通讯录,上传之后,业务组解析通讯录文件并转化为业务组需要的数据,最后持久化到数据库中。
基础以上场景,这个业务实际要进行两段操作:
附件组件:上传通讯录文件
附件组件上传成功后通知业务组回调函数
业务组回调函数拿到上传文件信息,并调用业务组自己的后端接口:后端解析Excel文件,并转化为业务组数据持久化到数据库
业务组后端接口:返回页面,告知用户成功或失败信息。
从上面过程看,从第三步开始与附件上传的标准过程不同,需要调用者来处理。
(1)编写前端代码:
首先,业务组需要在JSP页面准备好一个回调函数:
<script type="text/javascript">
//附件上传后回调方法
function testCallBack(file,d){
// 业务组处理文件逻辑的动作
var fileUrl = file.get(0).fileUrl;
var fileId = file.get(0).id;
sendAjax(fileUrl,fileId);
}
</script>
然后,参照标准模式,定义附件组建区域,唯一要增加的是:在附件组件comp属性增加callMethod:'testCallBack'
参数。
其它附件组件相关comp属性均参照标准模式的属性列表
<div class="comp" comp="type:'fileupload',callMethod:'testCallBack'">
<input type="button" onclick="insertAttachment()" value="上传附件">
(2)编写后端代码:
后端存在两种情况:
- 不保存附件信息,即获取到上传文件后,获取到文件数据后该文件不再使用,不需要作为附件存储起来。
- 保存附件信息。
场景一:业务组不保存附件信息
通过fileManager#getFile可以得到刚上传的文件:
public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView("apps/file/selfupload");
// 获取刚上传的文件对象
File file = fileManager.getFile(Long.parseLong(request.getParameter("fileid"),new Date()));
//对得到的文件进行处理
modelAndView.addObject("filename", file.getName());
modelAndView.addObject("filelength", file.length());
return modelAndView;
}
场景二:业务组自己保存附件信息
在后端业务操作中调用如下接口,用来关联附件也业务数据:
/**
* 根据文件标识新引用
* @param fileUrl 文件标识
* @param referenceId 业务id
*/
public void updateReference(Long fileUrl, Long referenceId);
/**
* 根据文件标识更新引用及子引用
* @param fileUrl 文件标识
* @param referenceId 业务主ID
* @param subReference 业务子ID
*/
public void updateReferenceSubReference(Long fileUrl, Long referenceId, Long subReference);
1 | 与该业务ID相关的所有附件都在同一处显示,使用该接口更新。 |
---|---|
2 | 与该业务ID相关的所有附件都在同多处显示,每处根据子ID进行区分,使用该接口更新。 |
# 附件上传-js动态创建方式
如果业务组不需要编写附件组件<div comp=fileupdate>
相关代码,只需要用前端Javascript直接操作附件上传组件,则可以使用本方案。
通过调用js方法:dymcCreateFileUpload() 来实现。对于不需要的特性输入null即可。
/**
* locationElementid, 位置id,放置上传组件的位置,比如div的id("dyncid"):<div id="dyncid"> </div>
* applicationCategory, 应用模块id
* extensions, 文件扩展名,逗号分隔的字符串
* quantity, 最多上传的文件数
* isEncrypt, 是否加密
* callMethod, 回调方法名
* attachmentTrId, 对赢得文件上传的id
* firstSave,是否先保存附件表信息,默认false:后保存。
* atts 附件数据
* canDeleteOriginalAtts 是否可删除附件
* takeOver 是否接管附件上传(即弹出窗口关闭)之后的逻辑。 该属性和callMethod配合使用,如果不使用回调方法,可以不使用该属性; 否则属性值应为false
* maxSize 上传文件的大小限制,单位为字节
*/
function dymcCreateFileUpload(locationElementid,applicationCategory,extensions,quantity,isEncrypt,callMethod, attachmentTrId,firstSave,canDeleteOriginalAtts,atts,takeOver,maxSize){
对于以上方式不能满足交互需要,可以使用下面接口灵活控制附件相关特性。
/**
* 获取当前组件提交的附件数据。对于一页存在多个上传组件,每个组件所在区域单独处理附件时(即只处理本区域附件,其他区域附件不处理),
* 使用该方法,可以把该组件上传的附件数据,存放到以组件ID为domainid的区域内。
* inputDomainId 上传组件id
*/
function saveAttachmentPart(inputDomainId ){
← Form校验提交组件 关联文档组件 →
