struts2文件上传
文件上传的方法,使用了struts的拦截器拦截action请求,把文件信息和存储字段信息保存到中间表中,这里只把保存的代码贴出来,展示和下载的方法实现起来比较多样,但是简单!
这里有一篇博客讲的是文件上传流程,可以参考学习:http://www.cnblogs.com/yjhrem/articles/2243007.html
1 public class UploadFile extends SysEntity { 2 3 private static final long serialVersionUID = 1L; 4 5 存储文件名 6 private String storageFileName; 7 上传文件名 8 private String uploadFileName; 9 上传文件大小10 private String size; 11 文件类型12 private String contentType; 13 文件扩展名14 private String extName; 15 16 public UploadFile() { 17 } 18 19 public UploadFile(String storageFileName, String uploadFileName, String size,String contentType, String extName) { 20 this.storageFileName = storageFileName; 21 this.uploadFileName = uploadFileName; 22 this.size = size; 23 this.contentType = contentType; 24 this.extName = extName; 25 } 26 get set方法 省略....... 27 }
3 import java.io.File; 4 import java.io.IOException; 5 import java.lang.reflect.InvocationTargetException; 6 import java.util.ArrayList; 7 import java.util.Collection; 8 import java.util.Enumeration; 9 import java.util.Iterator; 10 import java.util.List; 11 import java.util.UUID; 12 import java.util.regex.Matcher; 13 import java.util.regex.Pattern; 14 15 import javax.servlet.http.HttpServletRequest; 16 17 import org.apache.commons.beanutils.PropertyUtils; 18 import org.apache.commons.io.FileUtils; 19 import org.apache.commons.lang.StringUtils; 20 import org.apache.commons.lang3.ArrayUtils; 21 import org.apache.struts2.ServletActionContext; 22 import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper; 23 import org.slf4j.Logger; 24 import org.slf4j.LoggerFactory; 25 import org.springframework.mock.web.MockMultipartHttpServletRequest; 26 import org.springframework.web.multipart.MultipartFile; 34 import com.opensymphony.xwork2.ActionContext; 35 import com.opensymphony.xwork2.ActionInvocation; 36 import com.opensymphony.xwork2.interceptor.AbstractInterceptor; 37 38 /** 39 * 存储文件到服务器 40 * 41 * 文件中可定义storageDIR属性(存储目录)[系统默认路径为应用发布路径/uploadFiles目录] 如果与 42 * <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> 一同使用需要放置在其后面 43 * @see org.apache.struts2.interceptor.FileUploadInterceptor 44 */ 45 public class UploadFileInterceptor extends AbstractInterceptor { 46 47 private static final long serialVersionUID = 1L; 48 49 private static final Logger LOG = LoggerFactory.getLogger(UploadFileInterceptor.class); 50 public final static String[] NO_SUFFIX_ALLOWED = new String[] { "sql", "jsp", "cmd", "bat", "sh", "exe" };//例外的文件格式 51 52 public String intercept(ActionInvocation invocation) throws Exception { 53 ActionContext ac = invocation.getInvocationContext(); 54 HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST); 55 if (request instanceof MultiPartRequestWrapper && invocation.getAction() instanceof ActionParam) { 56 savedFilesToServer((MultiPartRequestWrapper) request, invocation.getAction()); 57 } 58 return invocation.invoke(); 59 } 60 61 /** 62 * 将文件存储到服务器 63 * 64 * @return 存储文件名,上传文件名 65 * @throws IOException 66 */ 67 private void savedFilesToServer(MultiPartRequestWrapper multiWrapper, Object actionObj) { 68 Enumeration<String> fileParameterNames = multiWrapper.getFileParameterNames(); 69 while (fileParameterNames != null && fileParameterNames.hasMoreElements()) { 70 String formItemName = fileParameterNames.nextElement(); 71 if (!checkEntityProperty(actionObj, formItemName)) {// 检查目标是否符合要求 72 continue; 73 } 74 File storageDIRFile = SysUtils.getUploadDir();//这里获得上传文件的路径,配置在配置文件中 75 if (!storageDIRFile.exists() || !storageDIRFile.isDirectory()) { 76 if (!storageDIRFile.mkdir()) { 77 LOG.error("[附件]文件上传失败,无法创建存储目录。请手工修改app.properties中的storageDIR存储路径[存储目录:" + storageDIRFile.getAbsoluteFile() + "]"); 78 break; 79 } 80 } 81 82 File[] file = multiWrapper.getFiles(formItemName); 83 String[] fileName = multiWrapper.getFileNames(formItemName); 84 String[] contentType = multiWrapper.getContentTypes(formItemName); 85 String uploadFileIds = ""; 86 List<UploadFile> ufs = new ArrayList<UploadFile>(); 87 BaseDAO dao = SpringContextUtil.getBean("baseDAO");//获得带有sessionFactory的对象 88 for (int index = 0; index < file.length; index++) { 89 File currentFile = file[index]; 90 if (!currentFile.exists()) { 91 continue; 92 } 93 94 String uploadFileName = fileName[index]; 95 String extName = getExtName(uploadFileName); 96 if (ArrayUtils.contains(NO_SUFFIX_ALLOWED, extName.toLowerCase())) { 97 LOG.warn("[附件]:" + extName); 98 throw new BizException("不被允许上传的文件!文件名:" + uploadFileName); 99 } 100 if (currentFile.length() < 1) { 101 throw new BizException("上传的文件大小为0,请重新选择!"); 102 } 103 104 String storageFileName = UUID.randomUUID().toString() + "." + extName; 105 File storageFile = new File(storageDIRFile, storageFileName); 106 // 步骤1:存储文件到文件系统 107 try { 108 FileUtils.copyFile(currentFile, storageFile); 109 LOG.debug("[附件]已将文件" + uploadFileName + "存储到 " + storageDIRFile.getAbsolutePath() + " 目录中,存储文件名为: " + storageFileName); 110 } catch (Exception e) { 111 LOG.error("[附件]文件存储失败,文件信息[文件名:" + uploadFileName + ",文件大小:" + currentFile.length() + "]", e); 112 } 113 114 // 步骤2:存储文件信息到文件表 115 UploadFile uf = new UploadFile(storageFileName, uploadFileName, String.valueOf(currentFile.length()), contentType[index], extName); 116 try { 117 dao.saveUpdate(uf);//将文件信息保存到数据中库 118 ufs.add(uf); 119 dao.flush();//flush session 120 } catch (Exception e) { 121 LOG.error("[附件]无法将文件信息存入文件表,错误信息:", e); 122 FileUtils.deleteQuietly(storageFile);// 回滚事务 123 break; 124 } 125 126 uploadFileIds += "," + uf.getId(); 127 } 128 129 // 步骤3:添加编辑中的文件(id存储在hidden中) 130 String[] hiddenFileIds = multiWrapper.getParameterValues(formItemName); 131 if (hiddenFileIds != null && hiddenFileIds.length > 0) { 132 uploadFileIds += "," + StringUtils.join(hiddenFileIds, ","); 133 } 134 135 try { 136 // 步骤4:存储文件表ID到业务实体属性 137 if (uploadFileIds.length() > 1) { 138 uploadFileIds = uploadFileIds.substring(1); 139 } 140 //匹配一对多关系中多的一方需要上传附件 141 Matcher matcher = Pattern.compile("\\[\\d*\\]").matcher(formItemName); 142 if (matcher.find()) { 143 String[] fileSystemNames = multiWrapper.getFileSystemNames(formItemName); 144 String[] fields = matcher.replaceAll("").split("\\."); 145 if (fields.length == 1) {// members[1] 仅支持集合,不支持数组 146 setFileId2Collection(uploadFileIds, fileSystemNames, fields[0], PropertyUtils.getProperty(actionObj, fields[0]), actionObj); 147 } else if (fields.length == 2) {// members[1].fileId 148 setFileId2Collection(uploadFileIds, fileSystemNames, fields[1], PropertyUtils.getProperty(actionObj, fields[0]), null); 149 } else if (fields.length == 3) {// entity.members[1].fileId 150 setFileId2Collection(uploadFileIds, fileSystemNames, fields[2], 151 PropertyUtils.getProperty(actionObj, fields[0] + "." + fields[1]), null); 152 } else { 153 PropertyUtils.setProperty(actionObj, formItemName, uploadFileIds); 154 } 155 } else { 156 PropertyUtils.setProperty(actionObj, formItemName, uploadFileIds); 157 } 158 } catch (Exception e) { 159 LOG.error("[附件]无法为附件属性赋值[Action对象名:" + actionObj.toString() + ",属性名:" + formItemName + "]", e); 160 for (UploadFile uf : ufs) { 161 dao.delEntity(uf); 162 FileUtils.deleteQuietly(new File(storageDIRFile, uf.getStorageFileName()));// 回滚事务 163 } 164 dao.flush(); 165 } 166 } 167 } 168 169 private void setFileId2Collection(String uploadFileIds, String[] fileSystemNames, String field, Object obj, Object root) 170 throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { 171 Iterator<?> iterator = Collection.class.cast(obj).iterator(); 172 boolean setted = false; 173 int index = 0; 174 while (iterator.hasNext()) { 175 if (setted) { 176 break; 177 } 178 179 Object next = iterator.next(); 180 String tempFilePath = String.valueOf(null == root ? PropertyUtils.getProperty(next, field) : next); 181 for (int i = 0; i < fileSystemNames.length; i++) { 182 if (tempFilePath.indexOf(fileSystemNames[i]) != -1) { 183 if (null == root) { 184 PropertyUtils.setProperty(next, field, uploadFileIds); 185 } else { 186 PropertyUtils.setProperty(root, field + "[" + index + "]", uploadFileIds); 187 } 188 setted = true; 189 break; 190 } 191 } 192 193 index++; 194 } 195 } 196 197 /** 198 * 获取扩展名 199 * 200 * @param fileName 201 * @return 202 */ 203 private String getExtName(String fileName) { 204 return StringUtils.substringAfterLast(fileName, "."); 205 } 206 207 /** 208 * 检查实体属性 209 * 210 * @param bean 211 * @param formItemName 212 * @return 213 */ 214 private boolean checkEntityProperty(Object bean, String formItemName) { 215 boolean flag = true; 216 try { 217 Matcher matcher = Pattern.compile("\\[\\d*\\]").matcher(formItemName); 218 if (matcher.find()) { 219 formItemName = matcher.replaceAll("[0]"); 220 } 221 222 Class<?> type = PropertyUtils.getPropertyType(bean, formItemName); 223 if (!String.class.equals(type)) { 224 LOG.warn("[附件上传]业务实体中提供接收附件的属性非String类型,无法将附件表ID赋值到该属性中。修改属性类型。[Action对象名:" + bean.toString() + ",属性名" + formItemName + ",属性类型:" 225 + type.getName() + "]"); 226 flag = false; 227 } 228 } catch (Exception e) { 229 LOG.warn("[附件上传]未找到对应属性,无法为附件属性赋值。请确认属性名和表单项名是否一致[附件表单项名:" + formItemName + "]"); 230 flag = false; 231 } 232 233 return flag; 234 } 235 }
这里需要考虑的是输入我这条记录的文件在删除的时候并不会删除UploadFile表中的数据,当然也不会删除我们保存的文件,长远考虑应该删除;