您的位置 首页 java

手把手教你学javaweb(五)文件的上传和下载

在进行文件的上传和下载之前,我们先把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="#34; prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "#34;>
<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="#34; prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "#34;>
<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;
    }

}

  

功能测试

文件的删除和下载都是好用的

文章来源:智云一二三科技

文章标题:手把手教你学javaweb(五)文件的上传和下载

文章地址:https://www.zhihuclub.com/168918.shtml

关于作者: 智云科技

热门文章

网站地图