JAVA 08 综合项目 文件的上传与下载,登录

tech2022-09-22  69

文件上传下载

<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">

同时接受表单的Servlet必须加入注解,否则无法接受传输方式为multipart/form-data的表单

// 1.添加注解 MultipartConfig 单个不可超过5M ,总共不可超过20M,超过会产生错误页面,可以自己指定错误页面 @MultipartConfig(maxFileSize =1024*1024*5, maxRequestSize = 1024*1024*20)

文件上传

保存路径

使用真实路径,并放在WEB-INF路径下,避免客户直接从游览器中访问

String realPath = request.getServletContext().getRealPath("/WEB-INF/upload"); File dir = new File(realPath); if(!dir.exists()) { dir.mkdirs(); }

获取数据

使用getParts方法获取数据,对其遍历

Collection<Part> parts = request.getParts();

获取上传文件名,

若上传文件名为空,则是普通字段. 若不为空,则上传的是文件

String submittedFileName = part.getSubmittedFileName(); if(submittedFileName==null) { //普通字段 String name = part.getName(); String value = request.getParameter(name); System.out.println("获取的普通字段"+name+"--"+value); }

获取文件名

若submittedFileName不为空,则可以判断上传的是文件, 但IE游览器会把路径名同时提交,且会把分割符去掉,情况如下

所以我们改从请求头中获取文件名,

String header = part.getHeader("content-disposition");

从中截取到文件名

String filename = header.substring(header.lastIndexOf("filename=") + 10,header.length()-1); filename = filename.substring(filename.lastIndexOf("\\")+1);

生成新的文件名与存储路径

为防止用户上传的文件名重复,造成文件,以及一个文件中存储过多内容 我们使用工具类 生成新的文件名和新的存储文件夹

public class UploadUtils { // 使用UUID生成新文件名,避免上传文件时产生的覆盖 public static String makeNewFileName(String filename) { String uuid = UUID.randomUUID().toString().replace("-", ""); return uuid+"_"+filename; } // 生成一个新的目录 打散存储,避免都存在一个目录中 public static String makeNewPath(String path,String filename){ int num = filename.hashCode(); // 使用hashCode与15进行与操作,可获得小于16的随机数字 int path1 = num&0xf; int path2 = (num>>4)&0xf; String newPath = path + File.separator+path1+File.separator+path2; File dir = new File(newPath); if (!dir.exists()){ dir.mkdirs(); } return newPath; } }

最后将文件保存

// 生成新的文件名和路径,防止文件名相同,并打散存储 filename=UploadUtils.makeNewFileName(filename); String newPath = UploadUtils.makeNewPath(realPath,filename); //保存文件 part.write(newPath+File.separator+filename); //删除part, part是一个缓存,使用完删除 part.delete();

其他问题

上传文件为空

没有文件上传,判断文件为空

if (submittedFileName.equals("")) { System.out.println("上传文件为空"); continue; }

上传类型限制

通过后缀加以限制

// 用后缀限制上传的文件类型 //1. 创建list,保存可接受类型 String ext = filename.substring(filename.lastIndexOf(".")+1); List<String> allowExts = new ArrayList<>(); allowExts.add("jpg"); allowExts.add("txt"); if (!allowExts.contains(ext)){ System.out.println("上传类型不对"); continue; }

上传文件大小

上传文件时必须要加上此MultipartConfig注解

// 1.添加注解 MultipartConfig 单个不可超过5M ,总共不可超过20M,超过会产生错误页面,可以自己指定错误页面 @MultipartConfig(maxFileSize =1024*1024*5, maxRequestSize = 1024*1024*20)

文件下载

先列表展示,点击下载

遍历方法

遍历文件夹,将文件UUID文件名与正常文件名保存至map中

// 遍历可下载的文件,使用HashMap,key为带UUID的文件名,value为不带UUID的文件名 public static void lisFile(File dir, HashMap<String,String> map){ File[] files = dir.listFiles(); if (files != null) { for (File file : files) { // 目录 if (file.isDirectory()){ lisFile(file,map); }else { // 文件 String uuidFileName = file.getName(); String fileName = uuidFileName.substring(uuidFileName.indexOf("_")+1); map.put(uuidFileName,fileName); } } } }

获取map,转发到展示界面

// 1. 读取可下载文件,展示到列表中 String realPath = request.getServletContext().getRealPath("/WEB-INF/upload"); File dir = new File(realPath); HashMap<String,String> map = new HashMap<>(); UploadUtils.lisFile(dir,map); // 保存至request域,转发 request.setAttribute("map",map); request.getRequestDispatcher("/list.jsp").forward(request,response);

展示页面

<c:forEach var="entry" items="${map}"> <li> <c:url var="myurl" value="/download"> <c:param name="filename" value="${entry.key}"></c:param> </c:url> <a href="${myurl}">${entry.value}</a> </li> </c:forEach>

文件下载

根据游览器传回的filename,找到要下载的文件名,使用流读取,返回至游览器

// 乱码 request.setCharacterEncoding("utf-8"); String uuidFilename = request.getParameter("filename"); String filename = uuidFilename.substring(uuidFilename.indexOf("_") + 1); String realPath = request.getServletContext().getRealPath("/WEB-INF/upload"); // 相同filename的hashCode相同 ,filename为String型,相同字符串hashCode相同 String path = UploadUtils.makeNewPath(realPath, uuidFilename); File file = new File(path + File.separator + uuidFilename); if (file.exists()) { // 设置响应头 让游览器保存文件 对文件名编码,防止中文文件名 response.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8")); FileInputStream fis = new FileInputStream(file); ServletOutputStream outputStream = response.getOutputStream(); int len = 0; byte[] bytes = new byte[1024]; while ((len=fis.read(bytes))!=-1){ outputStream.write(bytes,0,len); } }else { response.setContentType("utf-8"); response.getWriter().write("文件不存在"); }

书籍添加

BeanUtils使用

populate使用反射,调用set方法为对象属性进行赋值,表单字段名必须与属性名大小写完全一致。 字段类型必须能够自动转换或者相同,否则报错,可以不对某个属性赋值。使用request.getParameterMap()获取表单中的值,类型均是String,若对象类中有不是String型的字段,一定要考虑如何对其赋值: 1.若表单中不存在这个字段,可以先不对这个字段赋值,它会是空的,可以在映射后再对其赋值。 2.表单中存在某个字段,且对象类中字段类型不为String,一定要先考虑是否能自动转换,不能自动转换的要先使用注册器转换

注册时间转换器,表单input type=“date” 对象类中java.util.Date

ConvertUtils.register(new Converter() { @Override public <T> T convert(Class<T> aClass, Object o) { String date =(String)o; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { return (T)sdf.parse(date); } catch (ParseException e) { e.printStackTrace(); } return null; } }, Date.class);

也可使用

ConvertUtils.register(new DateLocaleConverter(),Date.class);

使用populate方法对对象进行映射,填充属性,

Book book = new Book(); BeanUtils.populate(book, request.getParameterMap());

ConvertUtils.register注册转换器

当用到BeanUtils的populate、copyProperties方法或者getProperty,setProperty方法其实都会调用convert进行转换 但Converter只支持一些基本的类型,甚至连java.util.Date类型也不支持。而且当遇到不认识的类型时,会抛出异常来。 这个时候就需要给类型注册转换器。比如:意思是所以需要转成Date类型的数据都要通过DateLocaleConverter这个转换器的处理。 ConvertUtils.register(new DateLocaleConverter(), Date.class);

其他转换器

convertUtils.register(new DateConverter(), Date.class); convertUtils.register(new BooleanConverter(null), Boolean.class); convertUtils.register(new LongConverter(null), Long.class); convertUtils.register(new IntegerConverter(null), Integer.class); convertUtils.register(new DoubleConverter(null), Double.class);

使用转换器将字符串数组转换成长整型数组

["123","343",69"] -> [123,343,69] public static long[] getParamValues(HttpServletRequest req, String name){ String[] values = req.getParameterValues(name); if(values==null) return null; return (long[])ConvertUtils.convert(values, long.class); }
最新回复(0)