文件上传下载功能十分常见,本篇文章记录一下操作流程。
文件上传
流程
- 要有一个 form 标签,method=post 请求。
- form 标签的 encType 属性值必须为 multipart/form-data值。
- 在 form 标签中使用 input type=file 添加上传的文件。
- 编写服务器代码(Servlet 程序)接收,处理上传的数据。
encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器。
需要使用到commons-fileupload-1.2.1.jar 和commons-io-1.4.jar这两个jar包。
- ServletFileUpload 类,用于解析上传的数据。
- FileItem 类,表示每一个表单项。
- boolean ServletFileUpload.isMultipartContent(HttpServletRequest request);判断当前上传的数据格式是否是多段的格式。
- public List parseRequest(HttpServletRequest request)解析上传的数据。
- boolean FileItem.isFormField()。判断当前这个表单项是普通的表单项,还是上传的文件类型。
- String FileItem.getFieldName()。获取表单项name值。
- String FileItem.getString()。获取表单项的值。
- String FileItem.getName()。获取上传的文件名。
- void FileItem.write( file )。将上传的文件写到 参数 file 所指向抽硬盘位置 。
上传文件的表单:
1 2 3 4 5 6
| <form action="http://192.168.31.74:8080/jsp/upload" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username" /> <br> 头像:<input type="file" name="photo" > <br> <input type="submit" value="上传"> </form>
|
解析上传数据的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("文件上传"); if(ServletFileUpload.isMultipartContent(req)){ FileItemFactory fileItemFactory = new DiskFileItemFactory(); ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory); try { List<FileItem> list = servletFileUpload.parseRequest(req); for(FileItem fileItem:list){ if(fileItem.isFormField()){ System.out.println("表单属性名"+fileItem.getFieldName()); System.out.println("表单属性值"+fileItem.getString("UTF-8")); }else{ System.out.println("表单属性名"+fileItem.getFieldName()); System.out.println("上传的文件名"+fileItem.getName()); fileItem.write(new File("e:\\"+fileItem.getName())); } } } catch (Exception e) { e.printStackTrace(); } } }
|
当文件上传时,http请求头中Content-Type内容:
文件下载
常用API
- response.getOutputStream();
- servletContext.getResourceAsStream();
- servletContext.getMimeType();
- response.setContentType();
- response.setHeader(“Content-Disposition”, “attachment; fileName=1.jpg”); 这个响应头告诉浏览器。这是需要下载的。而 attachment 表示附件,也就是下载的一个文件。fileName=后面, 表示下载的文件名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String downloadName = "a.jpg"; ServletContext servletContext = getServletContext(); String type = servletContext.getMimeType("/file/" + downloadName); System.out.println(type); resp.setContentType(type); resp.setHeader("Content-Disposition","attachment;filename="+downloadName); InputStream is = servletContext.getResourceAsStream("/file/" + downloadName); ServletOutputStream os = resp.getOutputStream(); IOUtils.copy(is,os); }
|
一次性验证码的使用
表单重复提交有三种常见的情况:
一:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。 造成表单重复提交问题。解决方法:使用重定向来进行跳转
二:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败, 就会着急,然后多点了几次提交操作,也会造成表单重复提交。
三:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复 提交。
使用谷歌验证码jar包:kaptcha-2.3.2.jar,在web.xml中配置Servlet程序。
在表单中使用 img 标签去显示验证码图片并使用它。
1 2 3 4
| String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
|