【温故知新】Java web 开发(三)Form表单与上传下载文件
简介:在一和二的基础之上,这次来记录下如何在页面提交表单数据,以及文件的上传和下载整个流程,请求也不仅限于GET了,也有POST了。
1. 为了方便,在 webapp 下直接新建一个 index.html,内容如下
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>欢迎页</title>
</head>
<body>
<form action="/upload" method="POST" enctype="multipart/form-data">
站点名: <input type="text" name="name"><br />
网址: <input type="text" name="url" /><br />
作者: <input type="text" name="author" /><br />
上传文件: <input type="file" name="file" /><br />
上传文件2: <input type="file" name="file2" /><br />
<input type="submit" value="提交" />
</form>
</body> </html>
form 的 action指定请求路径,这里是/upload,也可以是 process.jsp这种。
method 这里用的是 POST, 其它 GET 也可以用在这里。
enctype 表示的是提交请求中的Content-Type是 multipart/form-data,适用于文件上传。这里展示下请求的样式:

input type="file" 使用的是 文件上传的组件
input type="submit" 会把有 name 属性的 input 字段提交给 action 所指示的请求。
2. 新建 FileUploadServlet 来处理文件上传
这里文件上传处理,使用了开源组件 commons-fileupload,maven 依赖如下:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
Servlet主要业务代码如下(代码里用到了jdk8的lamda表达式,确实省代码)
逻辑比较简单,就是用 ServletFileUpload 来解析 request,获取到提交的文件信息,由于几个非文件也一并提交了,所以需要判断分类处理。
文件的上传和下载都是要使用流的。
@WebServlet(name = "fileUploadServlet", urlPatterns = {"/upload"})
public class FileUploadServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message="";
try {
String savePath = request.getServletContext().getRealPath("/WEB-INF/upload");
String tmpPath = request.getServletContext().getRealPath("/WEB-INF/temp");
File file = new File(savePath);
if (!file.exists() && !file.isDirectory()) {
System.out.println(savePath + "目录不存在,需要创建");
file.mkdir();
}
File tmpFile = new File(tmpPath);
if (!tmpFile.exists() && !tmpFile.isDirectory()) {
System.out.println(tmpPath + "目录不存在,需要创建");
tmpFile.mkdir();
}
DiskFileItemFactory factory = new DiskFileItemFactory();
// 缓冲区大小设置
factory.setSizeThreshold(1024 * 100);
factory.setRepository(tmpFile);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setProgressListener((pBytesRead, pContentLength, arg2) -> System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead));
upload.setHeaderEncoding("UTF-8");
if (!ServletFileUpload.isMultipartContent(request)) {
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(1024 * 1024 *10);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024 * 1024 * 100);
List<FileItem> list = upload.parseRequest(request);
for (FileItem item : list) {
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString("UTF-8");
// form 表单提交过的 enctype="multipart/form-data"
request.setAttribute(name,value);
System.out.println(name + "=" + value);
} else {
String filename = item.getName();
System.out.println(filename);
if (filename == null || "".equals(filename.trim())) {
continue;
}
filename = filename.substring(filename.lastIndexOf(File.separator) + 1);
InputStream in = item.getInputStream();
FileOutputStream out = new FileOutputStream(savePath + File.separator + filename);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
//删除处理文件上传时生成的临时文件
item.delete();
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
message = "单个文件超出最大值!";
System.out.println(message);
request.setAttribute("message", message);
request.getRequestDispatcher("/WEB-INF/page/message.jsp").forward(request, response);
} catch (FileUploadBase.SizeLimitExceededException e) {
message = "上传文件总大小超出最大值!";
System.out.println(message);
request.setAttribute("message", message);
request.getRequestDispatcher("/WEB-INF/page/message.jsp").forward(request, response);
} catch (FileUploadException e) {
message = "上传文件失败!";
System.out.println(message);
request.setAttribute("message", message);
request.getRequestDispatcher("/WEB-INF/page/message.jsp").forward(request, response);
}
request.getRequestDispatcher("/WEB-INF/page/file_upload_result.jsp").forward(request, response);
}
}
3. file_upload_result.jsp 是展示上传结果的页面
这里有个细节需要注意,就是之前传的几个字段是用 multipart/form-data 上传的,那么解析的时候就不能直接用 getParameter了,为了方便起见,我在之前的处理过程中,事先 setAttribute 了一下。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>表单处理展示</title>
</head>
<body>
<%
String name = (String)request.getAttribute("name");
String url = (String)request.getAttribute("url");
String author = (String)request.getAttribute("author");
%>
<li>您输入的网站是:<%=name%></li>
<li>网站名是:<%=url%></li>
<li>作者:<%=author%></li><br />
<div>点击这里查看上传过的文件类别:<a href="/list">这里</a></div>
</body>
</html>
4. 上传文件列表展示
@WebServlet(name = "fileListServlet", urlPatterns = {"/list"})
public class FileListServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filePath = request.getServletContext().getRealPath("/WEB-INF/upload");
Map<String, String> map = new HashMap<>(8);
listFile(new File(filePath), map);
request.setAttribute("fileMap", map);
request.getRequestDispatcher("/WEB-INF/page/file_list.jsp").forward(request, response);
}
private void listFile(File file, Map<String, String> fileNameMap) {
if (file.isDirectory()) {
File[] fileList = file.listFiles();
for (File innerFile : fileList) {
listFile(innerFile, fileNameMap);
}
} else {
String fileName = file.getName();
fileNameMap.put(fileName, fileName);
}
}
}
展示的页面
<%@ page import="java.util.Map" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>文件展示页</title>
</head>
<body>
<%
Map<String, String> map = (Map<String, String>)request.getAttribute("fileMap");
if(map == null ||map.size() == 0) {
out.println("您还没有上传文件,请点击这里上传:<a href=/index.html>上传文件</a>");
}
for (String str: map.keySet()) {
out.println("文件名:" + str + " <a href=/download?fileName=" + URLEncoder.encode(map.get(str), "utf-8")+ ">下载</a><br />");
}
%>
</body>
</html>
5. 文件下载
下载文件有个需要注意的地方就是文件名的乱码问题。由于 HTTP 请求头必须是 ISO-8859-1 编码,传送的时候一定要改成这个编码
@WebServlet(name = "fileDownloadServlet", urlPatterns = {"/download"})
public class FileDownloadServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("fileName");
System.out.println("fileName before ============" + fileName);
String uploadPath = request.getServletContext().getRealPath("/WEB-INF/upload");
File file = findFilePath(fileName, new File(uploadPath));
if (file != null) {
response.setContentType("application/octet-stream");
fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("content-disposition", "attachment;filename=" + fileName);
FileInputStream input = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
input.close();
out.close();
} else {
request.setAttribute("message", "您要下载的资源不存在或者已被删除!");
request.getRequestDispatcher("/WEB-INF/page/message.jsp").forward(request, response);
}
}
private File findFilePath(String fileName, File file) {
if (file == null || !file.isDirectory()) {
return null;
} else {
for (File innerFile : file.listFiles()) {
if (innerFile.isFile()) {
if (innerFile.getName().equals(fileName)) {
return innerFile;
}
} else {
return findFilePath(fileName, innerFile);
}
}
}
return null;
}
}
6. 乱码问题(非全面总结,近记录下个人遇到的问题)
不是设置了 request.setCharacterEncoding("UTF-8"); 就不会出现乱码问题,还得看容器的设置,比如说 Tomcat 的话,得看 server.xml 中的两个配置 useBodyEncodingForURI="true" URIEncoding="UTF-8"
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8444"
useBodyEncodingForURI="true" URIEncoding="UTF-8"/>
7. input 与 button
【温故知新】Java web 开发(三)Form表单与上传下载文件的更多相关文章
- Django---CBV和FBV的使用,CBV的流程,给视图加装饰器,Request对象方法,属性和Response对象,form表单的上传
Django---CBV和FBV的使用,CBV的流程,给视图加装饰器,Request请求对象方法,属性和Response响应对象,form表单的上传 一丶CBV和FBV 在Django中存 ...
- JAVA入门[16]-form表单,上传文件
一.如何传递参数 使用 @RequestParam 可以传递查询参数.例如:http://localhost:8092/category/detail?id=1 @RequestMapping(&qu ...
- Ajax serialize()提交form表单不能上传file类型
前台form表单的提交方式有很多种,例如: 1. form表单submit直接提交的方法 2. Ajax提交的方法 3. jquery提交的方法 4. 原生js提交的方法 每一种方法都有它的优势和不足 ...
- 模拟form表单请求上传文件
发请求 public string CameraFileUpload(string url,string path,string serverPath,string uploadfileName) { ...
- java实操之使用jcraft进行sftp上传下载文件
sftp作为临时的文件存储位置,在某些场合还是有其应景的,比如对账文件存放.需要提供一个上传的工具类.实现方法参考下: pom.xml中引入类库: <dependency> <gro ...
- Java模拟表单POST上传文件
JAVA模拟表单POST上传文件 import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import java.io ...
- MVC下form表单一次上传多种类型的图片(每种类型的图片可以上传多张)
form表单一次上传多种类型的图片(每种类型的图片可以上传多张) controller中的action方法 public ActionResult UploadImage( ) { in ...
- java web service 上传下载文件
1.新建动态web工程youmeFileServer,新建包com,里面新建类FileProgress package com; import java.io.FileInputStream; imp ...
- 【转】Java IOUtils方式上传下载文件 on HDFS
[From]https://www.cnblogs.com/areyouready/p/9795442.html package com.css.hdfs04; import java.io.File ...
随机推荐
- 关于mybatis中llike模糊查询中#和$的使用
模糊查询: 工作中用到,写三种用法吧,第四种为大小写匹配查询 1. sql中字符串拼接 SELECT * FROM tableName WHERE name LIKE CONCAT(CONCAT('% ...
- 开发者说:Sentinel 流控功能在 SpringMVC/SpringBoot 上的实践
从用户的视角来感受一个开源项目的成长,是我们推出「开发者说」专栏的初衷,即在开发者进行开源项目选型时,提供更为立体的项目信息.专栏所有内容均来自作者原创/投稿,本文是「开发者说」的第6篇,作者 Jas ...
- 4818 Largest Empty Circle on a Segment (几何+二分)
ACM-ICPC Live Archive 挺水的一道题,直接二分圆的半径即可.1y~ 类似于以前半平面交求核的做法,假设半径已经知道,我们只需要求出线段周围哪些位置是不能放置圆心的即可.这样就转换为 ...
- BLOB类型对应Long binary,CLOB对应Long characters
BLOB类型对应Long binary,CLOB对应Long characters
- oracle WHERE子句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. 例如: (低效,执行时间1 ...
- SuperSocket证书节点新增配置属性 "storeLocation"
你可以指定你想要加载的证书的存储地点: <certificate storeName="My" storeLocation="LocalMachine" ...
- 洛谷P1310 表达式的值 题解 栈/后缀表达式的应用
题目链接:https://www.luogu.org/problem/P1310 本题涉及算法:栈.前缀表达式转后缀表达式,动态规划思想. 这道题目我思考了好长时间,第一时间让我做的话我也做不出来. ...
- H3C 配置Basic NAT
- MySQL——修改视图
修改视图是指修改数据库中存在的视图,当基本表的某些字段发生变化时,可以通过修改视图来保持与基本表的一致性. 1. 用 CREATE OR REPLACE VIEW 语句修改视图 语法格式 ...
- C# 从 short 转 byte 方法
本文告诉大家多个方法转换 short 和 byte 有简单的也有快的 快速简单的方法 static short ToShort(short byte1, short byte2) { return ( ...