在进行文件的上传和下载之前,我们先把javaweb项目做一点点的改动,那就是将LoginServlet的跳转由原来的forward方式改为 redirect方式
重定向到项目内部的另一个servlet里面。这样我们就可以将登录逻辑和home页数据的加载放在不同的servlet来处理了
- 新建HomeServlet 用来加载首页数据,暂时先只做页面跳转。代码如下
package com.cgy.demos.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/home")
public class HomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/WEB-INF/home.jsp").forward(req, resp);
}
}
改造LoginServlet,将页面转发改为 servlet重定向,改造完的LoginServlet代码如下
package com.cgy.demos.web.servlet;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userName = req.getParameter("userName");
String password = req.getParameter("password");
String verifyCode = req.getParameter("verifyCode");
//为防止机器请求 第一步要先验证验证码是否正确
String cacheCode = (String) req.getSession().getAttribute("verifyCode");
if (StringUtils.isBlank(verifyCode)) {
req.setAttribute("msg", "验证码不能为空");
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
if (!verifyCode.equalsIgnoreCase(cacheCode)) {//这里验证码不区分大小写
req.setAttribute("msg", "验证码错误");
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
if (StringUtils.isBlank(password)) {
req.setAttribute("msg", "密码不能为空");
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
if (StringUtils.isBlank(userName)) {
req.setAttribute("msg", "用户名不能为空");
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
if (!userName.equals("admin")) {
req.setAttribute("msg", "用户名不正确");
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
if (!password.equals("123456")) {
req.setAttribute("msg", "密码不正确");
req.getRequestDispatcher("/WEB-INF/index.jsp").forward(req, resp);
return;
}
req.getSession().setAttribute("userName", userName);
req.getSession().removeAttribute("verifyCode");
resp.sendRedirect(req.getContextPath()+"/home");
return;
}
}
这里的处理流程是,页面填写用户名密码---> LoginServlet 处理登录--->重定向到HomeServlet ---> forward到页面Home.jsp
文件上传功能的开发
在home.jsp添加上传文件的form表单代码如下
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="static/js/jquery-1.8.3.min.js"></script>
<title>Insert title here</title>
</head>
<body>
<img src="static/img/userinfo.jpg" height="40" width="40" />:<font size="6px">${userName}</font>
<h1>欢迎进入IT技术学习系统</h1>
<hr/>
<h2>文件上传</h2>
<form action="<%=request.getContextPath()%>/upload" method = "post" enctype="multipart/form-data">
<form action="<%=request.getContextPath()%>/upload" method = "post" enctype="multipart/form-data">
描述:<input type="text" name = "desc" /><br/><br/>
文件:<input type="file" name = "file"/><br/><br/>
<input type="submit" value="上传"/>
</form>
<hr/>
<br/><br/>
<form action="<%=request.getContextPath()%>/logout" method = "post">
<input type="submit" value="退出登录"/>
</form>
</body>
</html>
新增上传文件处理的UploadServlet 代码如下
package com.cgy.demos.web.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
try {
// 1. 创建工厂对象
FileItemFactory factory = new DiskFileItemFactory();
// 2. 文件上传核心工具类
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置大小限制参数
upload.setFileSizeMax(10 * 1024 * 102400); // 单个文件大小限制
upload.setSizeMax(50 * 1024 * 102400); // 总文件大小限制
upload.setHeaderEncoding("UTF-8"); // 对中文文件编码处理
// 判断
if (upload.isMultipartContent(request)) {
// 3. 把请求数据转换为list集合
List<FileItem> list = upload.parseRequest(request);
// 遍历
for (FileItem item : list) {
// 判断:普通文本数据
if (item.isFormField()) {
// 获取名称
String name = item.getFieldName();
// 获取值
String value = item.getString("UTF-8");//这里要用UTF-8编码,不然中文会乱码 默认ISO8859-1
System.out.println(value);
}
// 文件表单项
else {
/******** 文件上传 ***********/
// a. 获取文件名称
String name = item.getName();
if (StringUtils.isBlank(name)){
continue;
}
// ----处理上传文件名重名问题----
// a1. 先得到唯一标记
String id = UUID.randomUUID().toString();
// a2. 拼接文件名
name = id + "#" + name;
// b. 得到上传目录
String basePath = getServletContext().getRealPath("/upload");
// c. 创建要上传的文件对象
File file = new File(basePath, name);
// d. 上传
item.write(file);
item.delete(); // 删除组件运行时产生的临时文件
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
resp.sendRedirect(request.getContextPath()+"/home");
}
}
这里使用到了 file-upload 类库来完成文件的上传与配置
在webapp目录下建好上传文件的存放目录 upload
文件名一部分是固定原文件名,一部分是UUID 防止文件覆盖,中间用#相连
文件的下载功能开发
我们要下载的文件就是刚刚上传至upload目录下的文件,要下载必须先把文件在页面上展示出来。
- 在HomeServlet新增读取upload文件的逻辑 代码如下
package com.cgy.demos.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/home")
public class HomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//加载要下载的文件
List<Map<String,String>> list = new ArrayList<>();
String basePath = getServletContext().getRealPath("/upload");
File file = new File(basePath);
File[] files = file.listFiles();
for (File f : files) {
if (f.isFile()){
Map<String,String> info = new HashMap<>();
String fileName = f.getName();
String[] arr = fileName.split("#");
info.put("name",arr[1]);
info.put("id",arr[0]);
BigDecimal decimal = new BigDecimal(f.length());
String temSize = null;
BigDecimal gSize = decimal.divide(new BigDecimal(1024*1024*1024),2,BigDecimal.ROUND_HALF_UP);
BigDecimal mSize = decimal.divide(new BigDecimal(1024*1024),2,BigDecimal.ROUND_HALF_UP);
BigDecimal kSize = decimal.divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
if (gSize.compareTo(BigDecimal.ONE)>=0){
temSize = gSize.toString() + "G";
}else if (mSize.compareTo(BigDecimal.ONE)>=0){
temSize = mSize.toString() + "M";
}else if (kSize.compareTo(BigDecimal.ONE)>=0){
temSize = kSize.toString() + "K";
}else {
temSize = decimal.toString() + "B";
}
info.put("size",temSize);
list.add(info);
}
}
req.setAttribute("files",list);
req.getRequestDispatcher("/WEB-INF/home.jsp").forward(req, resp);
}
}
- 这里是将upload目录下所有的文件都读取到,并且获取文件的 名称,唯一标识(上传时生成的),文件大小(这里获取文件大小的逻辑非常不错,用户体验极佳)
- 在home.jsp页面新增 文件展示的表格 用到了 经典的jsp c标签 。在我开发的过程中,明显的感觉出 jsp的渲染速度极快,是thymeleaf、freemarker这些模板引擎所不能比的! home.jsp代码如下
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="static/js/jquery-1.8.3.min.js"></script>
<title>Insert title here</title>
</head>
<body>
<img src="static/img/userinfo.jpg" height="40" width="40" />:<font size="6px">${userName}</font>
<h1>欢迎进入IT技术学习系统</h1>
<hr/>
<h2>文件上传</h2>
<form action="<%=request.getContextPath()%>/upload" method = "post" enctype="multipart/form-data">
<form action="<%=request.getContextPath()%>/upload" method = "post" enctype="multipart/form-data">
描述:<input type="text" name = "desc" /><br/><br/>
文件:<input type="file" name = "file"/><br/><br/>
<input type="submit" value="上传"/>
</form>
<hr/>
<font color="green" size="5px">${msg}</font>
<table id="fileTable" >
<thead><tr><th>文件名称</th><th>唯一标识</th><th>文件大小</th><th>操作</th></thead>
<tbody>
<c:forEach items="${files}" var="file">
<tr>
<td style="width: 150px;">${file.name}</td>
<td style="width: 380px;">${file.id}</td>
<td style="width: 60px;">${file.size}</td>
<td style="width: 100px;"><a href='<%=request.getContextPath()%>/download?name=${file.name}&id=${file.id}'>下载</a>
<a href='<%=request.getContextPath()%>/download?name=${file.name}&id=${file.id}&option=del'>删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<hr/>
<br/><br/>
<form action="<%=request.getContextPath()%>/logout" method = "post">
<input type="submit" value="退出登录"/>
</form>
</body>
</html>
展示一下home.jsp的显示效果
这里专门挑选了 三个不同数量级大小的文件,展示一下文件大小的效果
- 文件下载和删除的DownloadServlet 开发 代码如下
package com.cgy.demos.web.servlet;
import sun.misc.BASE64Encoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String id = req.getParameter("id");
String fullName = id + "#" + name;
String basePath = getServletContext().getRealPath("/upload");
File file = new File(basePath, fullName);
String option = req.getParameter("option");
if ("del".equals(option)){
boolean flag = file.delete();
if (flag){
req.setAttribute("msg","删除成功");
}else {
req.setAttribute("msg","文件不存在");
}
req.getRequestDispatcher( "/home").forward(req,resp);
return;
}
InputStream in = new FileInputStream(file);
String downloadName = processFileName(req, name);
resp.setHeader("content-disposition", "attachment;fileName=" + downloadName);
resp.setContentLength((int) file.length());
OutputStream out = resp.getOutputStream();
byte[] b = new byte[1024];
int len = -1;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
// 关闭
out.close();
in.close();
}
public static String processFileName(HttpServletRequest request, String fileName) {
String codedfilename = null;
try {
String agent = request.getHeader("USER-AGENT");
if (agent.contains("MSIE")) {
// IE浏览器
codedfilename = URLEncoder.encode(fileName, "utf-8");
codedfilename = codedfilename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
codedfilename = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
codedfilename = URLEncoder.encode(fileName, "utf-8");
}
} catch (Exception e) {
e.printStackTrace();
}
return codedfilename;
}
}
功能测试
文件的删除和下载都是好用的
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。