附件上传主要涉及数据库表:
T_BAS_Attachment:附件表
T_BAS_BoAttchAsso:附件和业务单据关系表
T_HR_SHRAttachmentExt:sHR附件表
附件默认是存储在数据库的,以字节流的方式存放在T_BAS_Attachment表的FFile。
sHR标准附件上传逻辑:点击附件上传控件上传附件后,会同时在T_BAS_Attachment和T_HR_SHRAttachmentExt写入数据,T_HR_SHRAttachmentExt表此时的状态FState为20。点击保存单据时,会更新T_HR_SHRAttachmentExt的状态为10,并且往T_BAS_BoAttchAsso写入数据
如果需要将附件上传阿里OSS,并且不储存在数据库,可修改com.kingdee.shr.attachment.app.SHRAttachmentExtControllerBean的_updateAffterSaveForm方法。在保存单据的时候将T_BAS_Attachment表FFile的字节流取到,上传到阿里OSS,然后将T_BAS_Attachment表FFile清空,将阿里OSS文件路径存在T_BAS_Attachment的FRemotePath。下载时可以根据这个路径去阿里OSS下载。
附件上传:
1 package com.kingdee.shr.attachment.app; 2 3 import com.kingdee.bos.BOSException; 4 import com.kingdee.bos.Context; 5 import com.kingdee.bos.dao.ormapping.ObjectUuidPK; 6 import com.kingdee.bos.metadata.entity.EntityViewInfo; 7 import com.kingdee.bos.metadata.entity.FilterInfo; 8 import com.kingdee.bos.metadata.entity.FilterItemInfo; 9 import com.kingdee.bos.util.BOSUuid; 10 import com.kingdee.eas.base.attachment.AttachmentFactory; 11 import com.kingdee.eas.base.attachment.AttachmentInfo; 12 import com.kingdee.eas.base.attachment.BoAttchAssoFactory; 13 import com.kingdee.eas.base.attachment.BoAttchAssoInfo; 14 import com.kingdee.eas.base.attachment.IAttachment; 15 import com.kingdee.eas.base.attachment.IBoAttchAsso; 16 import com.kingdee.eas.base.attachment.common.OSSClientUtil; 17 import com.kingdee.eas.common.EASBizException; 18 import com.kingdee.shr.attachment.AttachmentState; 19 import com.kingdee.shr.attachment.SHRAttachmentExtCollection; 20 import com.kingdee.shr.attachment.SHRAttachmentExtInfo; 21 22 import java.util.Map; 23 import org.apache.log4j.Logger; 24 public class SHRAttachmentExtControllerBean extends AbstractSHRAttachmentExtControllerBean 25 { 26 /** 27 * 28 */ 29 private static final long serialVersionUID = -182628981203112646L; 30 private static Logger logger = Logger.getLogger("com.kingdee.shr.attachment.app.SHRAttachmentExtControllerBean"); 31 32 protected Map _getAttchIDByFileName(Context ctx, String boID, String fileName) throws BOSException, EASBizException { 33 return null; 34 } 35 36 protected void _updateAffterSaveForm(Context ctx, String billId, String ids) throws BOSException, EASBizException { 37 FilterInfo filterInfo = new FilterInfo(); 38 39 filterInfo.getFilterItems().add(new FilterItemInfo("bunding", ids)); 40 filterInfo.getFilterItems().add(new FilterItemInfo("state", Integer.valueOf(20))); 41 EntityViewInfo entityViewInfo = new EntityViewInfo(); 42 entityViewInfo.setFilter(filterInfo); 43 44 IBoAttchAsso boAttchAsso = BoAttchAssoFactory.getLocalInstance(ctx); 45 IAttachment attfactory = AttachmentFactory.getLocalInstance(ctx); 46 SHRAttachmentExtCollection collection = getSHRAttachmentExtCollection(ctx, entityViewInfo); 47 if (collection.size() > 0){ 48 //path:oss存放路径,shr/单据bostype/单据id/ 49 StringBuffer path = new StringBuffer(); 50 BOSUuid uuid = BOSUuid.read(billId); 51 path.append("shr/"); 52 path.append(uuid.getType().toString()); 53 path.append("/"); 54 path.append(billId); 55 path.append("/"); 56 for (int i = 0; i < collection.size(); ++i) { 57 SHRAttachmentExtInfo extInfo = collection.get(i); 58 AttachmentInfo ai = extInfo.getAttachment(); 59 //获取附件数据 60 ai = attfactory.getAttachmentInfo(new ObjectUuidPK(ai.getId())); 61 //附件内容 62 byte[] content = ai.getFile(); 63 //上传oss 64 OSSClientUtil.uploadOSS(ctx,"OSSPARAM",path.toString(),extInfo.getName(), content); 65 //附件在oss的路径:"shr/"+extInfo.getName()放到附件表的fRemotePath 66 ai.setRemotePath(path+extInfo.getName()); 67 //将附件表的附件内容清空 68 ai.setFile(null); 69 //修改附件数据 70 attfactory.save(ai); 71 72 BoAttchAssoInfo boAttchAssoInfo = new BoAttchAssoInfo(); 73 boAttchAssoInfo.setBoID(billId); 74 boAttchAssoInfo.setAssoBusObjType(BOSUuid.getBOSObjectType(billId, true) + ""); 75 boAttchAssoInfo.setAssoType("Added Accessories"); 76 boAttchAssoInfo.setAttachment(ai); 77 boAttchAsso.addnew(boAttchAssoInfo); 78 extInfo.setState(AttachmentState.SAVE); 79 extInfo.setBoID(billId); 80 save(ctx, extInfo); 81 } 82 } 83 } 84 }
OSSClientUtil是自己写的阿里OSS帮助类,具体上传OSS的代码可查看https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11174283.6.940.3a007da2Tg3e3t.
附件下载:附件下载如果指定下载路径的话,是会下载到服务器上的,不会下载到客户端电脑,如果直接读取流,可能会出现乱码
com.kingdee.shr.base.syssetting.web.controller.AttachmentUploadController
1 private String writeAttachementFile(HttpServletRequest request, HttpServletResponse response) 2 throws ShrWebBizException, BOSException, EASBizException 3 { 4 String attachId = request.getParameter("id"); 5 logger.error(new StringBuilder().append("++++++ attachment downloadAction : attachId = ").append(attachId).toString()); 6 if (StringUtils.isEmpty(attachId)) { 7 throw new ShrWebBizException("下载失败,文件id为空"); 8 } 9 SelectorItemCollection sic = new SelectorItemCollection(); 10 sic.add(new SelectorItemInfo("id")); 11 sic.add(new SelectorItemInfo("name")); 12 sic.add(new SelectorItemInfo("remotePath")); 13 sic.add(new SelectorItemInfo("simpleName")); 14 AttachmentInfo ai = AttachmentFactory.getRemoteInstance().getAttachmentInfo(new ObjectUuidPK(attachId),sic); 15 16 String serverPath = request.getSession().getServletContext().getRealPath(File.separator); 17 String fileDir = new StringBuilder().append("newAttachmentFoler").append(File.separator).append(StringFilter(attachId)).append(File.separator).toString(); 18 String realFileDir = new StringBuilder().append(serverPath).append(fileDir).toString(); 19 File file = new File(realFileDir); 20 if (!(file.exists())) { 21 file.mkdirs(); 22 } 23 String fileName = new StringBuilder().append(ai.getName()).append(".").append(ai.getSimpleName()).toString(); 24 String realFileName = new StringBuilder().append(realFileDir).append(fileName).toString(); 25 System.out.println("realFileName:"+realFileName); 26 System.out.println("fileName:"+fileName); 27 System.out.println("serverPath:"+serverPath); 28 System.out.println("fileDir:"+fileDir); 29 System.out.println("realFileDir:"+realFileDir); 30 //下载到服务端 31 Context ctx = SHRContext.getInstance().getContext(); 32 OSSClientUtil.downloadOSS(ctx,"OSSPARAM",ai.getRemotePath(),realFileName); 33 OutputStream out = null; 34 FileInputStream input = null; 35 try { 36 input = new FileInputStream(realFileName); 37 response.reset(); 38 setResponseHeader(request, response, fileName); 39 if (input != null) { 40 AttachmentDownloadServer downServer = new AttachmentDownloadServer(); 41 byte[] content = downServer.getContent(input); 42 out = response.getOutputStream(); 43 out.write(content); 44 } 45 //删除下载到服务端的文件 46 del(realFileDir); 47 48 }catch (IOException e) { 49 }finally{ 50 try{ 51 closeStream(out); 52 input.close(); 53 } catch (ShrWebBizException e) { 54 throw new ShrWebBizException("下载失败", e); 55 } catch (IOException e) { 56 ExceptionUtil.newEasbizException(e); 57 } 58 } 59 return null; 60 }
这边使用的方式是先下载到服务端,再去服务端读取文件,最后把服务端的这个文件删除。
另外,员工信息列表界面有批量上传附件。这个需要改动com.kingdee.eas.hr.emp.web.util.PersonAttachmentBatchUploadHelper
1 private static boolean insertPersonAttachment(EmpHRORelationHisCollection empHRORelationHisColl, String fileName, String typeName, byte[] byteArray, Map panelMap, ZipFile zfile) throws BOSException, EASBizException 2 { 3 IAttachment attachment = AttachmentFactory.getRemoteInstance(); 4 IBoAttchAsso attchAsso = BoAttchAssoFactory.getRemoteInstance(); 5 String boID = ""; 6 String onlyone = "true"; 7 String propertyName = "null0"; 8 String description = ""; 9 String uipk = (String)panelMap.get("uipk"); 10 String panelName = (String)panelMap.get("name"); 11 String userId = HRFilterUtils.getCurrentUserId(SHRContext.getInstance().getContext()); 12 13 ISHRAttachmentExt SHRAttchExt = SHRAttachmentExtFactory.getRemoteInstance(); 14 SHRAttachmentExtInfo attchExt = new SHRAttachmentExtInfo(); 15 String personStr = ""; 16 String fileRealName = ""; 17 String mainname = ""; 18 String extname = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()); 19 extname = extname.toLowerCase(); 20 if (fileName.indexOf("##") == -1) { 21 personStr = fileName.substring(0, fileName.lastIndexOf(".")); 22 fileRealName = panelName + "." + extname; 23 mainname = panelName; 24 } else { 25 personStr = fileName.substring(0, fileName.indexOf("##")); 26 fileRealName = fileName.substring(fileName.indexOf("##") + 2); 27 if (fileRealName.lastIndexOf(".") == 0) { 28 fileRealName = panelName + "." + extname; 29 } 30 mainname = fileRealName.substring(0, fileRealName.lastIndexOf(".")); 31 } 32 PersonInfo pInfo = getPersonInfo(personStr); 33 if (pInfo == null) { 34 throw new EmployeeBosBizException(EmployeeBosBizException.EMP_NOT_EXIST_OR_ATTCH_INCON_REQ, new Object[] { personStr }); 35 } 36 37 PersonInfo person = null; 38 int i = 0; for (int size = empHRORelationHisColl.size(); i < size; ++i) { 39 person = empHRORelationHisColl.get(i).getPerson(); 40 if (pInfo.getNumber().equals(person.getNumber())) { 41 break; 42 } 43 person = null; 44 } 45 if (person == null) { 46 throw new EmployeeBizException(EmployeeBizException.NOT_IN_ADMINI_EARE, new Object[] { fileName }); 47 } 48 CoreBaseInfo entityInfo = getCoreBaseInfo(panelMap, pInfo); 49 if (entityInfo == null) { 50 throw new EmployeeBosBizException(EmployeeBosBizException.EMP_PAGE_INFO_NOT_EXIST, new Object[] { personStr, panelName }); 51 } 52 boID = entityInfo.getId().toString(); 53 54 AttachmentInfo ai = new AttachmentInfo(); 55 ai.setName(mainname); 56 ai.setSimpleName(extname); 57 ai.setDescription(description); 58 // ai.setFile(byteArray); 59 ai.setIsShared(false); 60 ai.setSharedDesc(SHRWebResource.getString("com.kingdee.eas.hr.emp.EmployeeBizResource", "label177", SHRContext.getInstance().getContext())); 61 62 //附件上传到阿里云 63 //FIle 清空 64 StringBuffer path = new StringBuffer(); 65 String bostype = entityInfo.getId().getType().toString(); 66 path.append("shr/"); 67 path.append(bostype); 68 path.append("/"); 69 path.append(boID); 70 path.append("/"); 71 //上传oss 72 OSSClientUtil.uploadOSS(null,"OSSPARAM",path.toString(),fileRealName, byteArray); 73 System.out.println(path.toString()); 74 System.out.println(fileRealName); 75 //附件在oss的路径:"shr/"+extInfo.getName()放到附件表的fRemotePath 76 ai.setRemotePath(path+fileRealName); 77 78 79 80 81 ai.setAttachID("" + System.currentTimeMillis()); 82 ai.setType(getFileType(fileRealName)); 83 84 attchExt.setAttachment(ai); 85 attchExt.setName(fileRealName); 86 attchExt.setPropertyName(propertyName); 87 if (propertyName.startsWith("null")) 88 attchExt.setType(AttachmentTypeEnum.FORM); 89 else { 90 attchExt.setType(AttachmentTypeEnum.PROPERTY); 91 } 92 attchExt.setState(AttachmentState.UNSAVE); 93 attchExt.setBunding(userId + ‘#‘ + uipk); 94 attchExt.setBoID(boID); 95 attchExt.setState(AttachmentState.SAVE); 96 97 attachment.addnew(ai); 98 99 if ((Boolean.valueOf(onlyone).booleanValue()) && (!(StringUtils.isEmpty(boID)))) { 100 attchExt.setState(AttachmentState.SAVE); 101 BoAttchAssoInfo boAttchAssoInfo = new BoAttchAssoInfo(); 102 boAttchAssoInfo.setBoID(boID); 103 boAttchAssoInfo.setAssoBusObjType(String.valueOf(BOSUuid.getBOSObjectType(boID, true))); 104 boAttchAssoInfo.setAssoType("Added Accessories"); 105 boAttchAssoInfo.setAttachment(ai); 106 attchAsso.addnew(boAttchAssoInfo); 107 } 108 109 SHRAttchExt.addnew(attchExt); 110 return true; 111 }