环境配置:导入依赖 jar 包。

commons-fileupload-1.4.jar

commons-io-2.6.jar

上传表单的enctype属性
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。

语法
<form enctype="value">
1
属性值
值 描述
application/x-www-form-urlencoded 在发送前编码所有字符(默认)
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain 空格转换为 “+” 加号,但不对特殊字符编码。主要用于大量文本数据的传递
ServletFileUpload对象解析请求
ServletFileUpload类是Apache组件处理文件上传的核心高级类,通过使用parseRequest(HttpServletRequest)方法可以将HTML中每个表单提交的数据封装成个Fileltem对象,然后以List列表的形式返回。

ServletFileUpload类方法
序号 方法名称 方法描述
1 void setSizeMax (long sizeMax) 设置请求信息内容的最大允许字 节数
2 List parseRequest (HttpServletRequest request) 解析form表单提交的数据返回一个 Fileltem实例的集合
3 static final boolean isMultipartContent (HttpServlet Requestrequest) 判断请求提交的方式是否是“multi- part/form-data”类型
4 void setHeaderEncoding (String encoding) 设置转换时所使用的字符集编码
ServletFileUpload详细简绍

FileItem接口常用方法

序号 方法名称 方法描述
1 public boolean isFormField() 判断Fileltem对象所封装的数据类型,普通表单字段返 回true,文件表单字段返回false
2 public String getName () 获得文件字段中所上传的文件名,普通表单字段调用此 方法返回 null
3 public String getFieldName () 返回表单字段元素的name属性值
4 public void write (File file) 将Fileltem对象中保存的文件数据内容写入指定的文 件中
5 public String getString () 将Fileltem对象中保存的主体内容以一个字符串返回, 其有一个重载方法getString(String encoding),可指定 所采用的编码集
6 public long getSize() 返回单个上传文件的字节数
FileItemFactory 接口的常用方法

序号 方法名称 方法描述
1 public void setSizeThreshold (int sizeThreshold) 设置内存缓冲区的大小
2 pubic void setRepositoryPath (String path) 设置临时文件存放的目录
文件上传
① 表单数据提交方式:POST
② 表单提交数据的类型:<form ... enctype=multipart/form-data>...</form>
③ 表单中设置文件上传项:<input type="file" ... />

页面

<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>使用Commons-FileUpload组件实现文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/FileUpload" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="userName">
    <br>
<%--    加上multiple属性实现一次上次多个文件--%>
    选择文件:<input type="file" name="myFile" multiple>
    <br>
    <input type="submit" value="上传"></form>
</body>
</html>

servlet页面

package file;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;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.io.PrintWriter;
import java.util.Iterator;
import java.util.List;/**
 * @author: BRILIANT屠一乐
 * @date: 2022/12/2 15:41
 * @description:
 */@WebServlet(description = "FileUpload", urlPatterns = {"/FileUpload"})
public class FileUpload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html");
        //enctype 属性是否是multipart/form-data
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        //获取输出流
        PrintWriter writer = response.getWriter();
        //上传者
        String userName = "";
        //上传的文件名,最后输出用
        StringBuffer fileStr = new StringBuffer("");
        try {
            if (isMultipart) {
                //创建工厂实例
                FileItemFactory factory = new DiskFileItemFactory();
                //ServletFileUp-load实例依赖于FileItemFactory工厂
                ServletFileUpload upload = new ServletFileUpload(factory);
                //解析表单字段 封装成一个FileItem实例的集合
                List<FileItem> itemList = upload.parseRequest(request);
                //迭代器
                Iterator<FileItem> iterator = itemList.iterator();
                while (iterator.hasNext()) {
                    //依次解析每一个FileItem实例,即表单
                    FileItem fileItem = iterator.next();
                    if (fileItem.isFormField()) {
                        //普通表单字段
                        //如果表单属性name的值的userName, 就获取这个表单字段的值
                        if (fileItem.getFieldName().equals("userName")) {
                            //getString方法:重载方法getString(String encoding),可指定所采用的编码集
                            userName = fileItem.getString("UTF-8");
                        }
                    } else {
                        //文件表单字段
                        // getName()获得文件字段中所上传的文件名,普通表单字段调用此方法返回 null
                        String fileUpName = fileItem.getName();//用户上传的文件名
                        File file = new File("E:\\idea_program\\Web\\file\\src\\main\\webapp\\temp\\" + fileUpName);//要保存到的文件
                        if (!file.exists()) {
//                            file.createNewFile();//一开始肯定是没有的,所以先创建出来
                        }
                        fileItem.write(file);//写入,保存到目标文件
                        fileStr.append(fileUpName + "、");
                    }
                }
                fileStr.replace(fileStr.lastIndexOf("、"), fileStr.length(), "");
                writer.print("<script>alert('用户" + userName + "上传了文件" + fileStr + "')</script>");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



文件下载
jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>
<h1>文件下载列表</h1>
<a href=" down.do? path=<%=getServletContext().getRealPath("1.png")%>">
    QQ图片20220704200735.jpg
</a><br>
<a href=" down.do? path=<%=getServletContext().getRealPath("deity.rar")%>">
    deity.rar
</a><br>
<a href=" down.do? path=<%=getServletContext().getRealPath("maggie.rar")%>">
    maggie.rar
</a><br>
<a href=" down.do? path=<%=getServletContext().getRealPath("rvncsse.rar")%>">
    rvncsse.rar
</a><br>
</body>
</html>



servlet页面

package sunyang; /**
 * @author: BRILIANT屠一乐
 * @date: 2022/12/3 19:39
 * @description:
 */import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.*;@WebServlet("/Download")
public class Download extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("下载");
        System.out.println(request.getParameter("path"));
        String path = new String(request.getServletContext().getRealPath("1.png").getBytes("iso-8859-1"));
        File file = new File(path);
        InputStream in = new FileInputStream(file);
        //通过响应建立输出流
        OutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes("gbk"), "iso-8859-1"));
        response.addHeader("Content-Length", String.valueOf(file.length()));
        response.setCharacterEncoding("utf-8");
        //通知浏览器以下载的方式打开
        response.setContentType("application/octet-stream");
        int data = 0;
        while ((data = in.read()) != -1) {
            os.write(data);
        }
        os.close();
        in.close();
    }    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }
}

博客迁移dca3eb4c-07fc-443b-b497-abaf1dcf935c

直接使用Servlet类和输入/输出流实现。与访问服务器文件不同的是,要实现文件的下载,不仅需要指定文件的路径,该需要在HTTP协议中设置两个响应消息头,如下

//设定接收程序处理数据的方式
Content-Disposition:attachment; filename =
//设定实体内容的MIME类型
Content-Type:application/x-msdownload

参考文章:http://blog.ncmem.com/wordpress/2023/11/25/javaweb实现文件上传和下载/