使用fileupload组件完成文件的上传应用
1)需求:
Ⅰ。上传
> 在upload.jsp页面上使用jQuery实现"新增一个附件",”删除附件“,但至少需要保留一个。
> 对文件的扩展名和文件的大小进行验证,以下的规则是可配置的,而不是写死在程序中的
>>文件的扩展名必须为.pptx,docx,doc
>>每个文件的大小不能超过1M
>>总的文件大小不能超过5M
> 若验证失败,则在upload.jsp页面上显示错误信息:
>> 若某一个文件不符合要求:xxx文件扩展名不合法或xxx文件大小超过1M
>> 总的文件大小不能超过5M
> 若验证通过,则进行文件的上传操作
>>文件上传,并给一个不能和其他文件重复的名字,但扩展名不变
>>在对应的数据表中添加一条记录
id file_name file_path file_desc
jsp页面:
<%-- Created by IntelliJ IDEA. User: dell Date: 2019/7/22 Time: 10:19 To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %>Title ${msg }
配置文件:
exts=pptx,docx,docfile.max.size=1048576total.file.max.size=5242880
配置文件实例化的类
package entity;import java.util.HashMap;import java.util.Map;public class FileUploadAppProperties { private Mapproperties = new HashMap<>(); private FileUploadAppProperties(){} private static FileUploadAppProperties instance = new FileUploadAppProperties(); public static FileUploadAppProperties getInstance(){ return instance; } public void addProperties(String propertyName,String propertyValue){ properties.put(propertyName,propertyValue); } public String getProperty(String propertyName){ return properties.get(propertyName); }}
监听:
package listener;import entity.FileUploadAppProperties;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import java.io.IOException;import java.io.InputStream;import java.util.Map;import java.util.Properties;public class FileUploadAppListener implements ServletContextListener { public FileUploadAppListener() { } @Override public void contextInitialized(ServletContextEvent sce) { InputStream in = getClass().getClassLoader().getResourceAsStream("WEB-INF/upload.properties"); Properties properties = new Properties(); try { properties.load(in); for (Map.Entry
Servlet
package servlet;import entity.FileUploadAppProperties;import entity.FileUploadBean;import exception.InvalidExtNameException;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.util.*;public class FileUploadServlet extends HttpServlet { private static final String FILE_PATH = "/WEB-INF/files/"; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String path = null; ServletFileUpload upload = getServletFileUpload(); try { //把需要上传的FileItem都放入到该Map中 //键:文件的待存放的路径,值:对应的FileItem对象 MapuploadFiles = new HashMap (); //解析请求,得到FileItem的集合 List items = upload.parseRequest(req); //1.构建FileUploadBean的集合,同时填充uploadFiles List beans = buildFileUploadBeans(items,uploadFiles); //2.校验扩展名 vaidateExtName(beans); //3.校验文件的大小:在解析时,已经校验了,我们只需要通过异常得到结果 //4.进行文件的上传操作 upload(uploadFiles); //5.把上传的信息保存到数据库中 saveBeans(beans); path = "/upload/success.jsp"; } catch (Exception e) { e.printStackTrace(); path = "/upload/upload.jsp"; req.setAttribute("msg",e.getMessage()); } req.getRequestDispatcher(path).forward(req,resp); } private ServletFileUpload getServletFileUpload() { String exts = FileUploadAppProperties.getInstance().getProperty("exts"); String fileMaxSize = FileUploadAppProperties.getInstance().getProperty("file.max.size"); String totalFileMaxSize = FileUploadAppProperties.getInstance().getProperty("total.file.max.size"); DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(1024 * 500); File tempDirectory = new File("d:\\tempDirectory"); factory.setRepository(tempDirectory); ServletFileUpload upload = new ServletFileUpload(factory); upload.setSizeMax(Integer.parseInt(totalFileMaxSize)); upload.setFileSizeMax(Integer.parseInt(fileMaxSize)); return upload; } private void saveBeans(List beans) { } /** * 校验扩展名是否合法 * @param beans */ private void vaidateExtName(List beans) { String exts = FileUploadAppProperties.getInstance().getProperty("exts"); List extList = Arrays.asList(exts.split(",")); for (FileUploadBean bean : beans ) { String fileName = bean.getFileName(); String extName = fileName.substring(fileName.lastIndexOf(".")+1); if (!extList.contains(extName)){ throw new InvalidExtNameException(fileName + "扩展名不合法"); } } } /** * 利用传入的FileItem的集合,构建FileUploadBean的集合,同时填充uploadFiles * FileUploadBean对象封装了:id,fileName,file'P'ath,fileDesc * uploadFiles:Map 类型,存放文件域类型的FileItem。键:待保存的文件的名字,值:FileItem对象 * 构建过程: * 1.遍历FileItem的集合,得到desc的Map ,键:desc的fieldName(desc1,desc2...), * * 2.遍历FileItem的集合,得到文件域额那些FileItem对象,构建对应的key(desc1...)来获取其desc,构建的FileUploadBean对象,并填充beans和uploadFiles。 * @param items * @param uploadFiles * @return */ private List buildFileUploadBeans(List items, Map uploadFiles) { List beans = new ArrayList<>(); //1.遍历FileItem的集合,先得到desc的Map ,其中键:fieldName(desc1,desc2...), //值表单域对应字段的值 Map descs = new HashMap<>(); for (FileItem item : items ) { if (item.isFormField()) descs.put(item.getFieldName(),item.getString()); } //2.遍历FileItem的集合,得到文件域的FileItem对象 //每得到一个FileItem对象都创建一个FileUploadBean对象 //得到fileName,构建filePath,从1的Map中得到当前FileItem对应的那个desc。 //使用fileName后面的数字去匹配 for (FileItem item : items ) { if (!item.isFormField()){ String fieldName = item.getFieldName(); String index = fieldName.substring(fieldName.length()-1); String fileName = item.getName(); String desc = descs.get("desc" + index); String filePath = getFilePath(fileName); FileUploadBean bean = new FileUploadBean(fileName,filePath,desc); beans.add(bean); uploadFiles.put(filePath,item); } } return beans; } /** * 根据指定的文件名构建一个随机的文件名 * 1.构建的文件的文件名的扩展名和给定的文件的扩展名一致 * 2.利用ServletContext的getRealPath方法获取的绝对路径 * 3.利用Random和当前的系统时间构建随机的文件的名字 * @param fileName * @return */ private String getFilePath(String fileName) { String extName = fileName.substring(fileName.lastIndexOf(".")); Random random = new Random(); int randomNumber = random.nextInt(100000); String filePath = getServletContext().getRealPath(FILE_PATH)+"\\" + System.currentTimeMillis()+ randomNumber + extName; return filePath; } /** * 文件上传前的准备工作,得到filePath和InputStream * @param uploadFiles * @throws IOException */ private void upload(Map uploadFiles) throws IOException { for (Map.Entry uploadFile : uploadFiles.entrySet() ) { String filePath = uploadFile.getKey(); FileItem item = uploadFile.getValue(); upload(filePath,item.getInputStream()); } } /** * 文件上传的io方法 * @param filePath * @param inputStream * @throws IOException */ private void upload(String filePath, InputStream inputStream) throws IOException { OutputStream out = new FileOutputStream(filePath); byte[] buffer = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer))!=-1){ out.write(buffer,0,len); } inputStream.close(); out.close(); }}
异常:
package exception;public class InvalidExtNameException extends RuntimeException { public InvalidExtNameException(String msg){ super(msg); }}