/* * Copyright (C) 2010---2014 星星(wuweixing)<349446658@qq.com> * * This file is part of Wabacus * * Wabacus is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.wabacus.system.fileupload; import java.io.File; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import org.apache.commons.fileupload.FileItem; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.wabacus.config.resource.dataimport.configbean.AbsDataImportConfigBean; import com.wabacus.system.assistant.DataImportAssistant; import com.wabacus.system.assistant.FilePathAssistant; import com.wabacus.system.dataimport.DataImportItem; import com.wabacus.system.dataimport.queue.UploadFilesQueue; import com.wabacus.system.dataimport.thread.FileUpDataImportThread; import com.wabacus.system.intercept.AbsFileUploadInterceptor; import com.wabacus.util.Tools; public abstract class AbsFileUpload { private final static Log log=LogFactory.getLog(AbsFileUpload.class); protected HttpServletRequest request; protected String contentType; protected Map<String,String> mFormFieldValues; protected AbsFileUploadInterceptor interceptorObj; public AbsFileUpload(HttpServletRequest request) { this.request=request; this.contentType=request.getHeader("Content-type"); } public Map<String,String> getMFormFieldValues() { return mFormFieldValues; } public void setMFormFieldValues(Map<String,String> formFieldValues) { mFormFieldValues=formFieldValues; } public AbsFileUploadInterceptor getInterceptorObj() { return interceptorObj; } protected String getRequestString(String paramname,String defaultvalue) { String paramvalue=null; if(contentType!=null&&contentType.startsWith("multipart/")) { paramvalue=(String)request.getAttribute(paramname); if(paramvalue==null||paramvalue.trim().equals("")) paramvalue=defaultvalue; else paramvalue=paramvalue.trim(); }else { paramvalue=Tools.getRequestValue(request,paramname,defaultvalue); } return paramvalue; } protected static String getFileNameFromAbsolutePath(String filepath) { String filename=filepath; if(File.separator.equals("/")) { filepath=Tools.replaceAll(filepath,"\\","/"); int idxsep=filepath.lastIndexOf("/"); if(idxsep>=0) filename=filepath.substring(idxsep+1); }else { filepath=Tools.replaceAll(filepath,"/","\\"); int idxsep=filepath.lastIndexOf("\\"); if(idxsep>=0) filename=filepath.substring(idxsep+1); } return filename.trim(); } protected String showDataImportFileUpload(List<String> lstDataImportFileNames) { if(lstDataImportFileNames==null||lstDataImportFileNames.size()==0) return ""; StringBuffer resultBuf=new StringBuffer(); resultBuf.append("<table border=0 cellspacing=1 cellpadding=2 style=\"margin:0px\" width=\"98%\" ID=\"Table1\" align=\"center\">"); resultBuf.append("<tr class=filetitle><td style='font-size:13px;'>数据文件上传</td></tr>"); StringBuffer fileNameBuf=new StringBuffer(); int idx=0; for(String filenameTmp:lstDataImportFileNames) { fileNameBuf.append(filenameTmp).append("; "); resultBuf.append("<tr><td style='font-size:13px;'><input type=\"file\" contentEditable=\"false\" name=\"uploadfile"+(idx++) +"\"></td></tr>"); } if(fileNameBuf.length()>2&&fileNameBuf.charAt(fileNameBuf.length()-2)==';') { fileNameBuf.deleteCharAt(fileNameBuf.length()-2); } resultBuf.append("<tr class=filetitle><td style='font-size:13px;'>[上传文件名:"+fileNameBuf.toString().trim()+"]</td></tr>"); resultBuf.append("<tr><td style='font-size:13px;'><input type=\"submit\" class=\"cls-button\" name=\"submit\" value=\"上传\">"); resultBuf.append("</td></tr></table>"); return resultBuf.toString(); } protected String uploadDataImportFiles(List lstFieldItems,List<AbsDataImportConfigBean> lstDiBeans,boolean isAsyn,PrintWriter out) { if(lstDiBeans==null||lstDiBeans.size()==0) { return "没有提供数据导入功能,不能上传数据导入文件"; } String filepath=lstDiBeans.get(0).getFilepath();//同一次上传的所有数据导入项的上传文件路径必须是一致的,所以这里只取第一个。 File f=new File(FilePathAssistant.getInstance().standardFilePath(filepath)); if(!f.exists()||!f.isDirectory()) { return "数据导入项"+lstDiBeans.get(0).getReskey()+"配置的filepath不存在或不是目录"; } Iterator itFieldItems=lstFieldItems.iterator(); FileItem itemTmp; Map<String,FileItem> mUploadFiles=new HashMap<String,FileItem>(); // List<String> lstAllFileNameAndPatterns=new ArrayList<String>();//存放本次上传对应的所有数据导入项不重复的filename属性值 List<String> lstFileNams=new ArrayList<String>(); String filepathTmp; while(itFieldItems.hasNext()) { itemTmp=(FileItem)itFieldItems.next(); if(itemTmp.isFormField()) continue; filepathTmp=itemTmp.getName(); if((filepathTmp==null||filepathTmp.equals(""))) continue; String filename=getFileNameFromAbsolutePath(filepathTmp); if(filename.equals("")) { return "文件上传失败,文件路径不合法"; } if(lstFileNams.contains(filename)) { return "文件"+filename+"不能重复上传"; } lstFileNams.add(filename); boolean shouldUpload=true; if(interceptorObj!=null) { shouldUpload=interceptorObj.beforeFileUpload(request,itemTmp,mFormFieldValues,out); } if(shouldUpload) { mUploadFiles.put(filename,itemTmp); } } if(mUploadFiles.size()==0) { return "没有取到要导入的数据文件"; } Map<List<DataImportItem>,Map<File,FileItem>> uploadFiles=new HashMap<List<DataImportItem>,Map<File,FileItem>>(); String errorinfo=generateUploadFilesAndImportItems(lstDiBeans,mUploadFiles,uploadFiles,filepath);//校验上传的数据文件与配置的数据导入项的关系是否正确 if(errorinfo!=null&&!errorinfo.trim().equals("")) return errorinfo; if(isAsyn) { UploadFilesQueue.getInstance().addUploadFile(uploadFiles); return null; }else { Entry<List<DataImportItem>,Map<File,FileItem>> entry=uploadFiles.entrySet().iterator().next(); return FileUpDataImportThread.getInstance().doDataImport(entry.getKey(),entry.getValue()); } } private String generateUploadFilesAndImportItems(List<AbsDataImportConfigBean> lstDiBeans,Map<String,FileItem> mUploadFiles, Map<List<DataImportItem>,Map<File,FileItem>> mResults,String filepath) { List<DataImportItem> lstDataImportItems=new ArrayList<DataImportItem>(); Map<File,FileItem> mUploadFileItems=new HashMap<File,FileItem>();//为了数据文件上传 mResults.put(lstDataImportItems,mUploadFileItems); List<String> lstTmpFile=new ArrayList<String>(); File fTmp; Map<String,File> mFileTmp=new HashMap<String,File>(); String[] strArrTmp; for(AbsDataImportConfigBean dibeanTmp:lstDiBeans) { lstTmpFile.clear(); for(String filenameTmp:mUploadFiles.keySet()) { strArrTmp=DataImportAssistant.getInstance().getRealFileNameAndImportType(filenameTmp); if(dibeanTmp.isMatch(strArrTmp[0])) { String file=FilePathAssistant.getInstance().standardFilePath(filepath+File.separator+filenameTmp); fTmp=mFileTmp.get(file); if(fTmp==null) { fTmp=new File(file); mFileTmp.put(file,fTmp); mUploadFileItems.put(fTmp,mUploadFiles.get(filenameTmp)); } DataImportItem diitem=new DataImportItem(dibeanTmp,fTmp); diitem.setRequest(request); diitem.setSession(request.getSession()); diitem.setDynimportype(strArrTmp[1]); lstDataImportItems.add(diitem); lstTmpFile.add(filenameTmp); } } if(lstTmpFile.size()==0) { log.warn("本次上传没有上传与数据导入项"+dibeanTmp.getReskey()+"匹配的数据文件"); }else if(lstTmpFile.size()>1) { log.warn("数据文件上传失败,数据导入项"+dibeanTmp.getReskey()+"与本次上传的多个数据文件名"+lstTmpFile+"匹配"); return "上传失败,同时上传了多个与"+dibeanTmp.getFilename()+"匹配的数据文件"; } } if(lstDataImportItems.size()==0) { return "没有上传有效的数据导入文件"; } return null; } protected String getSaveFileName(String name,String newfilename) { if(Tools.isEmpty(newfilename)) return name; String suffix=null; int idx=name.lastIndexOf("."); if(idx>0) suffix=name.substring(idx); suffix=suffix==null?"":suffix.trim(); name=newfilename; if(name.startsWith("{")&&name.endsWith("}")) { name=name.substring(1,name.length()-1).trim(); if(name.equalsIgnoreCase("date")) { name=Tools.getStrDatetime("yyyy-MM-dd",new Date()); }else if(name.equalsIgnoreCase("time")) { name=Tools.getStrDatetime("HH:mm:ss",new Date()); }else if(name.equalsIgnoreCase("timestamp")) { name=String.valueOf(System.currentTimeMillis()); }else { name=newfilename; } } return name+suffix; } protected String displayFileUpload(int uploadcount,String allowtypes,String disallowtypes) { StringBuilder resultBuf=new StringBuilder(); resultBuf.append("<table border=0 cellspacing=1 cellpadding=2 style=\"margin:0px\" width=\"98%\" ID=\"Table1\" align=\"center\">"); resultBuf.append("<tr class=filetitle><td style='font-size:13px;'>文件上传</td></tr>"); for(int i=0;i<uploadcount;i++) {//为每一种数据文件生成一个上传输入框 resultBuf.append("<tr><td style='font-size:13px;'><input type=\"file\" contentEditable=\"false\" name=\"uploadfile"+i+"\"></td></tr>"); } resultBuf.append(getAllowedFileSuffixPrompt(allowtypes,disallowtypes)); resultBuf.append("<tr><td style='font-size:13px;'><input type=\"submit\" class=\"cls-button\" name=\"submit\" value=\"上传\">"); return resultBuf.toString(); } private String getAllowedFileSuffixPrompt(String allowtypes,String disallowtypes) { StringBuilder resultBuf=new StringBuilder(); if(!Tools.isEmpty(allowtypes)||!Tools.isEmpty(disallowtypes)) { resultBuf.append("<tr class=filetitle><td style='font-size:13px;'>["); if(!Tools.isEmpty(allowtypes)) resultBuf.append(stardardFileSuffixString(allowtypes)); if(!Tools.isEmpty(disallowtypes)) { resultBuf.append("  disallowed:<font color='red'>"+stardardFileSuffixString(disallowtypes)+"</font>"); } resultBuf.append("]</td></tr>"); } return resultBuf.toString(); } protected String stardardFileSuffixString(String filesuffixes) { if(filesuffixes==null||filesuffixes.trim().equals("")) return ""; List<String> lstSuffixes=Tools.parseStringToList(filesuffixes.trim(),";",false); StringBuilder suffixBuf=new StringBuilder(); for(String typeTmp:lstSuffixes) { if(typeTmp==null||typeTmp.trim().equals("")||typeTmp.trim().equals(".")) continue; typeTmp=typeTmp.trim(); if(typeTmp.startsWith(".")) { typeTmp=typeTmp.substring(1).trim(); } suffixBuf.append(typeTmp.toLowerCase()).append(";"); } return suffixBuf.toString(); } protected List<String> getFileSuffixList(String filesuffixes) { if(filesuffixes==null||filesuffixes.trim().equals("")) return null; filesuffixes=filesuffixes.trim(); List<String> lstResults=new ArrayList<String>(); List<String> lstTemp=Tools.parseStringToList(filesuffixes,";",false); for(String filetype:lstTemp) { if(filetype==null||filetype.trim().equals("")) continue; filetype=filetype.trim(); if(filetype.startsWith(".")) { filetype=filetype.substring(1).trim(); if(filetype.equals("")) continue; } lstResults.add(filetype.toLowerCase().trim()); } return lstResults; } protected void getRealUploadFileName(List<String> lstDestFileNames,String originalFilename) { String destfilename=mFormFieldValues.get(AbsFileUploadInterceptor.FILENAME_KEY); if(Tools.isEmpty(destfilename)) destfilename=originalFilename; if(lstDestFileNames.contains(destfilename)) { int idx=destfilename.lastIndexOf("."); String nameTmp=idx>0?destfilename.substring(0,idx):destfilename; String suffix=idx>0?destfilename.substring(idx):""; idx=1; while(true) { if(!lstDestFileNames.contains(nameTmp+"("+(++idx)+")"+suffix)) break; } destfilename=nameTmp+"("+idx+")"+suffix; mFormFieldValues.put(AbsFileUploadInterceptor.FILENAME_KEY,destfilename); } lstDestFileNames.add(destfilename); } protected String doUploadFileAction(FileItem item,Map<String,String> mFormFieldValues,String orginalFilename,String configAllowTypes, List<String> lstConfigAllowTypes,String configDisallowTypes, List<String> lstConfigDisallowTypes) { String strmaxsize=mFormFieldValues.get(AbsFileUploadInterceptor.MAXSIZE_KEY); if(strmaxsize!=null&&!strmaxsize.trim().equals("")) { long lmaxsize=Long.parseLong(strmaxsize.trim()); if(lmaxsize>0&&lmaxsize<item.getSize()) return "上传失败,上传文件太大"; } if(!isInvalidUploadFileType(orginalFilename,configAllowTypes,lstConfigAllowTypes,configDisallowTypes,lstConfigDisallowTypes)) { return "文件上传失败,文件类型不合法"; } String savepathTmp=mFormFieldValues.get(AbsFileUploadInterceptor.SAVEPATH_KEY); String destfilenameTmp=mFormFieldValues.get(AbsFileUploadInterceptor.FILENAME_KEY); if(!Tools.isEmpty(savepathTmp)&&!Tools.isEmpty(destfilenameTmp)) { try { savepathTmp=FilePathAssistant.getInstance().standardFilePath(savepathTmp+File.separator); FilePathAssistant.getInstance().checkAndCreateDirIfNotExist(savepathTmp); item.write(new File(savepathTmp+destfilenameTmp)); }catch(Exception e) { log.error("上传文件"+orginalFilename+"到路径"+savepathTmp+"失败",e); return "上传文件"+orginalFilename+"到路径"+savepathTmp+"失败"; } } return null; } private boolean isInvalidUploadFileType(String orginalFilename,String configAllowTypes,List<String> lstConfigAllowTypes, String configDisallowTypes,List<String> lstConfigDisallowTypes) { String suffix=""; int idxdot=orginalFilename.lastIndexOf(".");//这里要用orginalFilename,不能用destfilename,因为是判断上传的原始文件名,而不是上传到服务器后的文件名 if(idxdot>0&&idxdot!=orginalFilename.length()-1) suffix=orginalFilename.substring(idxdot+1).toLowerCase().trim(); String allowTypesTmp=mFormFieldValues.get(AbsFileUploadInterceptor.ALLOWTYPES_KEY); if(!Tools.isEmpty(allowTypesTmp)) { List<String> lstAllowTypesTmp=allowTypesTmp.equalsIgnoreCase(configAllowTypes)?lstConfigAllowTypes:getFileSuffixList(allowTypesTmp); if(!Tools.isEmpty(lstAllowTypesTmp)&&!lstAllowTypesTmp.contains(suffix)) return false; } String disallowTypesTmp=mFormFieldValues.get(AbsFileUploadInterceptor.DISALLOWTYPES_KEY); if(!Tools.isEmpty(disallowTypesTmp)) { List<String> lstDisallowTypesTmp=disallowTypesTmp.equalsIgnoreCase(configDisallowTypes)?lstConfigDisallowTypes :getFileSuffixList(disallowTypesTmp); if(!Tools.isEmpty(lstDisallowTypesTmp)&&lstDisallowTypesTmp.contains(suffix)) return false; } return true; } public abstract void showUploadForm(PrintWriter out); public abstract String doFileUpload(List lstFieldItems,PrintWriter out); public abstract void promptSuccess(PrintWriter out,boolean isArtDialog); }