jeecg基础框架中对上传附件已经封装的相当不错了,只需要参照演示demo中的多附件管理的例子稍作修改就可以了(在”常用示例-多附件管理“下,另一个例子”上传下传“太简单了,一般项目中不可能这么简单的)。
先看一下jeecg基础框架自带的存储附件的表及实体中主要属性:
private TSUser TSUser;// 创建人 private String businessKey;// 业务类主键 private String subclassname;// 子类名称全路径 private String attachmenttitle;// 附件名称 private byte[] attachmentcontent;// 附件内容 private String realpath;// 附件物理路径 private Timestamp createdate; private String note; private String swfpath;// swf格式路径 private String extend;// 扩展名
其中businessKey就可以和我们的业务表来关联了,用来存储业务表的主键
下面主要记录一下参照基础框架中自带例子需要修改的地方:
controller
public ModelAndView addorupdate(ExprDelComEntity exprDelCom, HttpServletRequest req) { if (StringUtil.isNotEmpty(exprDelCom.getId())) { exprDelCom = exprDelComService.getEntity(ExprDelComEntity.class, exprDelCom.getId()); req.setAttribute("exprDelComPage", exprDelCom); List<TSAttachment> exprDelComFiles = exprDelComService.findByProperty(TSAttachment.class, "businessKey", exprDelCom.getId()); req.setAttribute("exprDelComFiles", exprDelComFiles); } return new ModelAndView("com/jason/logistics/express/exprDelCom"); }
这边除了需要根据id获取对应的实体实例外,还需要根据业务主键的id获取对应的附件列表,jeecg自带的例子是直接新建一个中间表t_finance_files(对应的实体为TFinanceFilesEntity)来保存附件表t_s_attachment与业务的关联,好处是可以在业务表建立一个与附件表的一对多的关系,在加载时只需要直接根据业务id来加载业务对象就可以了,在页面可以直接通过xxx.files这样来获取附件列表,而我这边直接利用附件表中的businessKey,好处是不需要多建一个对象和一张中间表,但需要在controller中额外的根据业务表的id获取对应的附件列表。
@RequestMapping(params = "delFile") @ResponseBody public AjaxJson delFile( HttpServletRequest request) { AjaxJson j = new AjaxJson(); String id = request.getParameter("id"); TSAttachment file = systemService.getEntity(TSAttachment.class, id); message = "" + file.getAttachmenttitle() + "被删除成功"; exprDelComService.deleteFile(file); systemService.addLog(message, Globals.Log_Type_DEL, Globals.Log_Leavel_INFO); j.setSuccess(true); j.setMsg(message); return j; }
增加一个delFile方法专门来用于处理删除文件的逻揖
@RequestMapping(params = "save") @ResponseBody public AjaxJson save(ExprDelComEntity exprDelCom, HttpServletRequest request) { AjaxJson j = new AjaxJson(); if (StringUtil.isNotEmpty(exprDelCom.getId())) { message = "快递公司信息更新成功"; ExprDelComEntity t = exprDelComService.get(ExprDelComEntity.class, exprDelCom.getId()); try { MyBeanUtils.copyBeanNotNull2Bean(exprDelCom, t); exprDelComService.saveOrUpdate(t); systemService.addLog(message, Globals.Log_Type_UPDATE, Globals.Log_Leavel_INFO); } catch (Exception e) { e.printStackTrace(); message = "快递公司信息更新失败"; } } else { message = "快递公司信息添加成功"; exprDelComService.save(exprDelCom); systemService.addLog(message, Globals.Log_Type_INSERT, Globals.Log_Leavel_INFO); } // j.setMsg(message); j.setObj(exprDelCom); return j; }
修改save方法,生成的代码是直接返回String类型的信息的,这边因为页面中需要获取业务实体的id及其它可能的属性,所以需要返回整个业务对象的实体(这边让我在开发过程中卡了一个壳)
@RequestMapping(params = "del") @ResponseBody public AjaxJson del(ExprDelComEntity exprDelCom, HttpServletRequest request) { AjaxJson j = new AjaxJson(); exprDelCom = systemService.getEntity(ExprDelComEntity.class, exprDelCom.getId()); message = "快递公司信息删除成功"; exprDelComService.deleteExprDelCom(exprDelCom); systemService.addLog(message, Globals.Log_Type_DEL, Globals.Log_Leavel_INFO); j.setMsg(message); return j; }
这边需要修改del方法,在删除业务实体时调用专门的方法deleteExprDelCom,而不是默认的基类的delete方法,是因为这边在删除对应的业务表的记录外还需要删除对应的附件表的实例及对应在磁盘中的文件。
@RequestMapping(params = "saveFiles", method = RequestMethod.POST) @ResponseBody public AjaxJson saveFiles(HttpServletRequest request, HttpServletResponse response, TSAttachment tSAttachment) { AjaxJson j = new AjaxJson(); Map<String, Object> attributes = new HashMap<String, Object>(); String fileKey = oConvertUtils.getString(request.getParameter("fileKey"));// 文件ID String exprDelComId = oConvertUtils.getString(request.getParameter("exprDelComId"));//快递公司ID if (StringUtil.isNotEmpty(fileKey)) { tSAttachment = systemService.getEntity(TSAttachment.class, fileKey); } // ExprDelComEntity exprDelCom = exprDelComService.getEntity(ExprDelComEntity.class, exprDelComId); tSAttachment.setBusinessKey(exprDelComId); UploadFile uploadFile = new UploadFile(request, tSAttachment); uploadFile.setCusPath("files"); uploadFile.setSwfpath("swfpath"); uploadFile.setByteField(null);//不存二进制内容 tSAttachment = systemService.uploadFile(uploadFile); attributes.put("fileKey", tSAttachment.getId()); attributes.put("viewhref", "commonController.do?objfileList&fileKey=" + tSAttachment.getId()); attributes.put("delurl", "commonController.do?delObjFile&fileKey=" + tSAttachment.getId()); j.setMsg("文件添加成功"); j.setAttributes(attributes); return j; }
增加saveFiles方法专门处理上传附件的逻辑
2. service
public interface ExprDelComServiceI extends CommonService{ void deleteFile(TSAttachment file); void deleteExprDelCom(ExprDelComEntity exprDelCom); }
接口中增加两个方法,一个是删除附件的方法,一个是删除业务实体的方法
@Service("exprDelComService") @Transactional public class ExprDelComServiceImpl extends CommonServiceImpl implements ExprDelComServiceI { /** * 附件删除 */ public void deleteFile(TSAttachment file) { //[1].删除附件 String sql = "select * from t_s_attachment where id = ?"; Map<String, Object> attachmentMap = commonDao.findOneForJdbc(sql, file.getId()); //附件相对路径 String realpath = (String) attachmentMap.get("realpath"); String fileName = FileUtils.getFilePrefix2(realpath); //获取部署项目绝对地址 String realPath = ContextHolderUtils.getSession().getServletContext().getRealPath("/"); FileUtils.delete(realPath+realpath); FileUtils.delete(realPath+fileName+".pdf"); FileUtils.delete(realPath+fileName+".swf"); //[2].删除数据 commonDao.delete(file); } /** * 快递公司删除 */ public void deleteExprDelCom(ExprDelComEntity exprDelCom) { //[1].上传附件删除 String attach_sql = "select * from t_s_attachment where id in (select id from t_finance_files where financeId = ?)"; List<Map<String, Object>> attachmentList = commonDao.findForJdbc(attach_sql, exprDelCom.getId()); for(Map<String, Object> map:attachmentList){ //附件相对路径 String realpath = (String) map.get("realpath"); String fileName = FileUtils.getFilePrefix2(realpath); //获取部署项目绝对地址 String realPath = ContextHolderUtils.getSession().getServletContext().getRealPath("/"); FileUtils.delete(realPath+realpath); FileUtils.delete(realPath+fileName+".pdf"); FileUtils.delete(realPath+fileName+".swf"); } //[2].删除资金管理 commonDao.delete(exprDelCom); } }
实现类中增加丙个方法的实现,只要根据jeecg例子的代码稍做修改即可。
3. 界面(jsp)
<script type="text/javascript"> $(function(){ //查看模式情况下,删除和上传附件功能禁止使用 if(location.href.indexOf("load=detail")!=-1){ $(".jeecgDetail").hide(); } }); function uploadFile(data){ $("#exprDelComId").val(data.obj.id); alert($(".uploadify-queue-item")); if($(".uploadify-queue-item").length>0){ upload(); }else{ frameElement.api.opener.reloadTable(); frameElement.api.close(); } } function close(){ frameElement.api.close(); } </script> <!-- 弹出页面窗口大小控制 --> <style type="text/css"> #formobj { height: 65%; min-height: 300px; overflow-y: auto; overflow-x: auto; min-width: 600px; } </style>
在新增修改界面<head>部分中增加专门处理与附件有关的代码,其中uploadFile方法是最主要的,当提交表单保存业务表的记录成功后会调用这个方法来继续上传附件,也就是说jeecg中处理上传附件是分两步来处理的
<t:formvalid formid="formobj" dialog="true" usePlugin="password" layout="table" callback="@Override uploadFile" action="exprDelComController.do?save">
这边使用了jeecg中的t:formvalid标签,注意默认生成的代码中callback这个属性是没有的,这边增加这个属性就是为了在表单提交成功后继续上传附件(@Override uploadFile),这边uploadFile就是对应前面增加的javascrip方法名了,而前面的@Override关键字我猜应该是默认已经有uploadFile这个方法了,这边是专门进行重写。
<tr> <td align="right"><label class="Validform_label"> 三证信息: </label></td> <td class="value"><input type="hidden" value="${exprDelComPage.id}" id="exprDelComId" name="exprDelComId" /> <table> <c:forEach items="${exprDelComFiles}" var="exprDelComFile"> <tr style="height: 34px;"> <td>${exprDelComFile.attachmenttitle}</td> <td><a href="commonController.do?viewFile&fileid=${exprDelComFile.id}&subclassname=org.jeecgframework.web.system.pojo.base.TSAttachment" title="下载">下载</a></td> <td><a href="javascript:void(0);" onclick="openwindow('预览','commonController.do?openViewFile&fileid=${exprDelComFile.id}&subclassname=org.jeecgframework.web.system.pojo.base.TSAttachment','fList','800','700')">预览</a></td> <td><a href="javascript:void(0)" class="jeecgDetail" onclick="del('exprDelComController.do?delFile&id=${exprDelComFile.id}',this)">删除</a></td> </tr> </c:forEach> </table></td> </tr> <tr> <td></td> <td class="value"><script type="text/javascript"> $.dialog.setting.zIndex =1990; function del(url,obj){ $.dialog.confirm("确认删除该条记录?", function(){ $.ajax({ async : false, cache : false, type : 'POST', url : url,// 请求的action路径 error : function() {// 请求失败处理函数 }, success : function(data) { var d = $.parseJSON(data); if (d.success) { var msg = d.msg; tip(msg); $(obj).closest("tr").hide("slow"); } } }); }, function(){ }); } </script> <div class="form" id="filediv"></div> <div class="form jeecgDetail"> <t:upload name="fiels" id="file_upload" extend="pic" buttonText="添加文件" formData="exprDelComId" uploader="exprDelComController.do?saveFiles"> </t:upload> </div> </td> </tr>
这边增加了附件显示和上传附件的控件部分,其中t:upload这个标签最主要的了,其中formData这个属性是设置在上传附件时需要一起提交的表单中的其它属性,一般只要提交业务实体的主键就可以了,而uploader这个属性对应的是上传附件的链接