jsp学习笔记之上传和下载(六)

六. 上传和下载

1. 上传

a. 引入两个JAR包

  • apache: commons- fileupload. jar组件
    • commons- fileupload. jar依赖commons- io. jar
      <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.1</version>
      </dependency>
      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
      </dependency>

b. 代码:

前台代码jsp:

  • 通过表单上传:
  • 表单的提交方式必须是post
  • 表单中必须增加一个属性:enctype="multipart/form-data"
    jsp学习笔记之上传和下载(六)_第1张图片

后台代码servlet:

使用tomcat部署项目时上传的目录有时会被删除:

如果修改代码,重新启动项目,项目会重新部署class文件

为防止上传目录丢失:a. 虚拟路径 b. 目录改为非tomcat内路径

示例:

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>上传和下载</title>
</head>
<body>
<center>
    请输入姓名、学号和要上传的文件(只能是png、jpg、gif类型)
    <div style="width:540px;border:1px solid black;background-color:#ddd">
        <form action="../../UploadServlet " id="form1" name="form1" method="post" enctype="multipart/form-data" >
            学号:<input type="text" name="uno" id="uno" ><br>
            姓名:<input type="text" name="uname" id="uname" ><br>
            上传照片:<input type="file" name="spicture" id="file"/>
            <input type="submit" value="提交">
        </form>
    </div>
</center>
</body>
<script type="text/javascript">
    function demo()
    {
        var name = document.getElementById("name");
        var pass = document.getElementById("pass");
        var file = document.form1.file.value.toString().trim().length;
        var errStr = "";
        if (uname.value == "" || uname.value == null)
        {
            errStr += "用户名不能为空\n";
        }
        if (uno.value == "" || uno.value == null)
        {
            errStr += "密码不能为空\n";
        }
        if (file <= 0)
        {
            errStr += "请选择要上传的文件\n";
        }
        if (errStr == "" || errStr == null)
        {
            return true;
        }
        alert(errStr);
        return false;
    }
    document.getElementById("form1").onsubmit = demo;
</script>
</html>

UploadServlet.java

package UpAndDown;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.Iterator;
import java.util.List;

/**
 * @Author: qsX
 * @Time: 2020-05-11 10:03
 * @Description: 上传的servlet
 */
@WebServlet("UploadServlet")
public class UploadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=UTF-8");
        try {
            //上传
            boolean isMultipart = ServletFileUpload.isMultipartContent(req);
            if (isMultipart) {//判断前台的form是否有mutipart属性
                DiskFileItemFactory factory = new DiskFileItemFactory();

                ServletFileUpload upload = new ServletFileUpload(factory);
                //设置上传文件时的临时文件的大小 10kb 缓冲区  factory = new DiskFileItemFactory()
                factory.setSizeThreshold(1024 * 10);
                String uploadtemp = req.getSession().getServletContext().getRealPath("uploadtemp");
                factory.setRepository(new File(uploadtemp));//设置临时文件目录
                //设置上传单个文件大小 20kb  upload = new ServletFileUpload(factory)
                upload.setSizeMax(1024 * 20);//字节
                //通过parseRequest解析form中的所有请求对象并保存到items集合中
                //(即前台传递的sno sname spicture此时就保存在了items中)
                List<FileItem> items = null;
                items = upload.parseRequest(req);
                //通过迭代器遍历items中的数据
                Iterator<FileItem> iter= items.iterator();
                while(iter.hasNext()) {
                    FileItem item = iter.next();
                    String itemName = item.getFieldName();
                    int sno = -1;
                    String sname = null;
                    //因为form中的属性enctype="multipart/form-data"所以不能用req.getParameter()
                    //只能用item.getString()判断匹配并赋值
                    if (item.isFormField()){//判断前合字段是普通form表单字段,还是文件字段
                        if (itemName.equals("sno")) {//根据name属性判断item是sno 还是sname 还是spicture
                            sno = Integer.parseInt(item.getString("utf-8"));
                        } else if (itemName.equals("sname")) {
                            sname = item.getString("utf-8");
                        } else {
                            System.out.println("其他字段");
                        }
                    } else {//文件上传
                        //先拿到文件名
                        //getFieldName是获取普通表单字段的Name值;getName()是获取文件名
                        String fileName = item.getName();
                        //通过获取文件名后缀来判断文件类型
                        String ext = fileName.substring(fileName.indexOf(".")+1);
                        if(!(ext.equals("png") || ext.equals("jpg") || ext.equals("gif"))) {
                            req.getRequestDispatcher("demo/UpAndDown/error.jsp").forward(req, resp);
                            return;//终止
                        }
                        //获取文件的内容,并上传
                        String path = req.getSession().getServletContext().getRealPath("upload");
                        //也可以写绝对路径
                        File file = new File(path,fileName);//指定上传的位置(服务器路径 )



                        item.write(file);
                        System.out.println(fileName+"上传成功!");
                        return;
                    }
                }
            }
        } catch (FileUploadBase.SizeLimitExceededException e) {
            e.printStackTrace();
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

2. 下载

a. 不需要依赖任何jar包

  1. 请求(地址a form),亲求Servlet
  2. Servlet通过文件的地址 , 将文件转为输入流 读到servlet中

b. 代码

1.下载文件必须设置消息头
resp.addHeader("contentType","MIME类型");
resp.addHeader("content-Disposition","attachment;filename=" + fileName);

文件类型 Content-Type
二进制文件(任何类型的文件) application/octet-stream
Word application/ msword
Execl application/vnd.ms-excel
PPT application/vnd.ms-powerpoint
图片 image/gif ,
文本文件 text/plain
html网页 text/html

示例:

jsp页面

t.jpg

DownloadServlet.java

package UpAndDown;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

/**
 * @Author: qsX
 * @Time: 2020-05-12 00:46
 * @Description: 下载
 */
@WebServlet("DownloadServlet")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        //获取要下载的文件名
        String fileName = req.getParameter("filename");//form \ a href \...Server?a=b
        //下载文件必须设置消息头
        resp.addHeader("content-Type","application/octet-stream");
        resp.addHeader("contentType","MIME类型");
        resp.addHeader("content-Disposition","attachment;filename=" + fileName);//fileName包含了文件后缀:abc.txt


        //2. Servlet通过文件的地址 , 将文件转为输入流 读到servlet中
        InputStream in = getServletContext().getResourceAsStream("/upload/" + fileName);

        //3. 通过输出流 将刚才转为输入流的文件输出给客户
        ServletOutputStream out = resp.getOutputStream();

        byte[] bs = new byte[10];
        int len = -1;
        while((len = in.read(bs)) != -1) {
            out.write(bs,0,len);
        }
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

c. 解决下载乱码问题

当下载文件名为中文时可能会乱码

  1. edge:
//当下载文件名是中文的时候可能会乱码,需要设置编码,如下
resp.addHeader("content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));

jsp学习笔记之上传和下载(六)_第2张图片

  1. firefox/chrome等
    给文件名加前缀 中 后缀

前缀:
中:String构造方法(Base64.)
后缀:?=

resp.addHeader("content-Disposition","attachment;filename==?UTF-8?B?"
+ new String(Base64.getEncoder().encodeToString(fileName.getBytes("UTF-8"))) +"?=");
  1. 为了使都兼容这边需要加一个判断
        //判断是什么浏览器,先获取user-agent
        String agent = req.getHeader("User-Agent");
        if (agent.toLowerCase().indexOf("safari") != -1) {
            resp.addHeader("content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        } else {
            resp.addHeader("content-Disposition","attachment;filename==?UTF-8?B?"
                    + new String(Base64.getEncoder().encodeToString(fileName.getBytes("UTF-8"))) +"?=");
        }
  1. 附带各浏览器的User-Agent

你可能感兴趣的:(jsp)