文件上传下载与一次性验证码

文件上传下载功能十分常见,本篇文章记录一下操作流程。

文件上传

流程

  • 要有一个 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 fileItemFactory = new DiskFileItemFactory();
//创建解析上传数据的ServletFileUpload对象
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);
//设置响应头告诉客户端收到的数据如何处理
//attachment表示附件
//filename是文件名
resp.setHeader("Content-Disposition","attachment;filename="+downloadName);
//通过servletContext获取文件输入流
InputStream is = servletContext.getResourceAsStream("/file/" + downloadName);
//response获取输出流
ServletOutputStream os = resp.getOutputStream();
//读取输入流的数据复制到输出流给客户端
IOUtils.copy(is,os);
}

一次性验证码的使用

表单重复提交有三种常见的情况:

一:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。 造成表单重复提交问题。解决方法:使用重定向来进行跳转

二:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败, 就会着急,然后多点了几次提交操作,也会造成表单重复提交。

三:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复 提交。

使用谷歌验证码jar包:kaptcha-2.3.2.jar,在web.xml中配置Servlet程序。

在表单中使用 img 标签去显示验证码图片并使用它。

1
2
3
4
// 获取 Session 中的验证码
String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
// 删除 Session 中的验证码,以防再次使用
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
Author

叶润繁

Posted on

2022-01-23

Licensed under