使用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" %> <html> <head> <title>Title</title> <script type="text/javascript" src="/jQuery/jquery-3.4.0.min.js"></script> <script type="text/javascript"> $(function () { var i =2; $("#addFile").click(function () { $(this).parent().parent().before("<tr class='file'><td>File" + i +":</td><td><input type='file' name='file" + i +"'></td></tr><tr class='desc'><td>Desc" + i +":</td><td><input type='text' name='desc" + i +"'><input type='button' id='delete" + i +"' value='删除'></input></td></tr>"); i++; //获取删除按钮 $("#delete" + (i-1)).click(function () { var $tr = $(this).parent().parent(); $tr.prev("tr").remove(); $tr.remove(); //对i重新排序 $(".file").each(function (index) { var n = index +1; $(this).find("td:first").text("File" + n); $(this).find("td:last input").attr("name","file"+n); }) $(".desc").each(function (index) { var n = index +1; $(this).find("td:first").text("Desc" + n); $(this).find("td:last input").attr("name","desc"+n); }) i--; }); }); }) </script> </head> <body> <font color="red">${msg }</font> <br><br> <form action="/FileUploadServlet" method="post" enctype="multipart/form-data"> <input type="hidden" id="fileNum" name="fileNum" value="1"> <table> <tr class="file"> <td>File1:</td> <td><input type="file" name="file1"></td> </tr> <tr class="desc"> <td>Desc1:</td> <td><input type="text" name="desc1"></td> </tr> <tr> <td><input type="submit" id="submit" value="提交"></td> <td><input type="button" id="addFile" value="新增一个附件"></td> </tr> </table> </form> </body> </html>
配置文件:
exts=pptx,docx,doc file.max.size=1048576 total.file.max.size=5242880
配置文件实例化的类
package entity; import java.util.HashMap; import java.util.Map; public class FileUploadAppProperties { private Map<String,String> properties = 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<Object,Object> prop: properties.entrySet() ) { String propertyName = (String) prop.getKey(); String propertyValue = (String) prop.getValue(); FileUploadAppProperties.getInstance().addProperties(propertyName,propertyValue); } } catch (IOException e) { e.printStackTrace(); } } @Override public void contextDestroyed(ServletContextEvent sce) { } }
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对象 Map<String,FileItem> uploadFiles = new HashMap<String,FileItem>(); //解析请求,得到FileItem的集合 List<FileItem> items = upload.parseRequest(req); //1.构建FileUploadBean的集合,同时填充uploadFiles List<FileUploadBean> 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<FileUploadBean> beans) { } /** * 校验扩展名是否合法 * @param beans */ private void vaidateExtName(List<FileUploadBean> beans) { String exts = FileUploadAppProperties.getInstance().getProperty("exts"); List<String> 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<String,FileItem>类型,存放文件域类型的FileItem。键:待保存的文件的名字,值:FileItem对象 * 构建过程: * 1.遍历FileItem的集合,得到desc的Map<String,string>,键:desc的fieldName(desc1,desc2...), * * 2.遍历FileItem的集合,得到文件域额那些FileItem对象,构建对应的key(desc1...)来获取其desc,构建的FileUploadBean对象,并填充beans和uploadFiles。 * @param items * @param uploadFiles * @return */ private List<FileUploadBean> buildFileUploadBeans(List<FileItem> items, Map<String, FileItem> uploadFiles) { List<FileUploadBean> beans = new ArrayList<>(); //1.遍历FileItem的集合,先得到desc的Map<String,string>,其中键:fieldName(desc1,desc2...), //值表单域对应字段的值 Map<String,String> 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<String, FileItem> uploadFiles) throws IOException { for (Map.Entry<String,FileItem> 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); } }