Jsp+Servlet实现文件上传下载 文件上传(一)

"JSP+Servlet实现文件上传下载",基本上可以分为文件上传和文件下载两个部分。下面详细讲解一下文件上传部分的实现过程。

文件上传实现

1. 文件上传表单页面

首先需要在页面上提供上传文件的表单。代码如下:

<form action="upload" method="post" enctype="multipart/form-data">
  请选择要上传的文件:<input type="file" name="file"><br/>
  <input type="submit" value="上传">
</form>

这个表单中,注意以下三点:

  • action 属性设为 "upload",表示文件上传的处理器的 url-pattern 属性值。
  • method 属性设为 "post",因为上传的文件可能比较大,需要使用 POST 方法上传。
  • enctype 属性设为 "multipart/form-data",表示 form 内容包含二进制数据。

2. 文件上传处理器

然后在 Servlet 中写文件上传处理器:

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // 检查是否为 multipart/form-data 表单
    if (!ServletFileUpload.isMultipartContent(req)) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Not a multipart request.");
      return;
    }

    // 配置上传参数
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload uploader = new ServletFileUpload(factory);
    uploader.setFileSizeMax(1024 * 1024 * 100); // 100 MB
    uploader.setSizeMax(1024 * 1024 * 500); // 500 MB

    // 上传文件
    List<FileItem> items = uploader.parseRequest(req);
    for (FileItem item : items) {
      if (item.isFormField()) {
        // 处理表单字段(非文件字段)
      } else {
        // 处理文件字段
        String fileName = item.getName();
        String contentType = item.getContentType();
        long sizeInBytes = item.getSize();
        InputStream dataInput = item.getInputStream();
        // 处理文件
      }
    }

    // 发送响应
    resp.getWriter().print("Upload done.");
  }
}

这个文件上传处理器中,注意以下几点:

  • @WebServlet 注解的 url-pattern 属性值设为 "upload",与表单的 action 属性一致。
  • @MultipartConfig 注解表示该 Servlet 是一个多部分文件上传的 Servlet。
  • 检查是否为 multipart/form-data 表单。
  • 配置上传参数,比如文件大小限制。
  • 上传文件,使用 ServletFileUpload 类的 parseRequest() 方法解析 HttpServletRequest 中的数据,并返回一个 List<FileItem> 集合。
  • 遍历 List<FileItem>,检查每个 FileItem 是表单字段还是文件字段。
  • 如果是表单字段(非文件字段),可以通过 FileItem 的 getString() 或 getInputStream() 方法获取其值。
  • 如果是文件字段,可以通过 FileItem 的 getName()、getContentType()、getSize() 和 getInputStream() 方法获取文件的元数据及内容。

下面是一个示例,将上传的文件都保存到服务器本地文件系统中。

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // 检查是否为 multipart/form-data 表单
    if (!ServletFileUpload.isMultipartContent(req)) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Not a multipart request.");
      return;
    }

    // 配置上传参数
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload uploader = new ServletFileUpload(factory);
    uploader.setFileSizeMax(1024 * 1024 * 100); // 100 MB
    uploader.setSizeMax(1024 * 1024 * 500); // 500 MB

    // 上传文件
    List<FileItem> items = uploader.parseRequest(req);
    String fileDir = "/path/to/your/upload/dir/";
    for (FileItem item : items) {
      if (item.isFormField()) {
        // 处理表单字段(非文件字段)
      } else {
        // 处理文件字段
        String fileName = item.getName();
        String contentType = item.getContentType();
        long sizeInBytes = item.getSize();
        InputStream dataInput = item.getInputStream();
        // 保存文件
        Path path = Paths.get(fileDir, fileName);
        Files.copy(dataInput, path, StandardCopyOption.REPLACE_EXISTING);
        // 处理文件
      }
    }

    // 发送响应
    resp.getWriter().print("Upload done.");
  }
}

上面这个例子中,上传的文件都会保存到文件系统的 "/path/to/your/upload/dir/" 文件夹下,如果该文件夹不存在会自动创建。路径可以根据实际情况修改。

3. 文件上传进度监控

文件上传过程中,用户可能需要看到上传的进度,提示上传过程是否成功。可以使用 Ajax 轮询的方式实现文件上传进度监控。以下是一个示例:

<script>
function pollProgress() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText != "") {
      var progress = JSON.parse(xhr.responseText);
      document.getElementById("progress").innerHTML = progress.percent + "%";
      if (progress.status == "IN_PROGRESS") {
        setTimeout(pollProgress, 1000); // 每秒轮询一次
      } else if (progress.status == "COMPLETED") {
        alert("Upload done.");
      } else if (progress.status == "FAILED") {
        alert("Upload failed.");
      }
    }
  };
  xhr.open("GET", "upload-progress", true);
  xhr.send();
}
</script>

<form onsubmit="pollProgress(); return false;">
  请选择要上传的文件:<input type="file" name="file"><br/>
  <input type="submit" value="上传">
</form>

<div id="progress"></div>

这个表单中,使用 onsubmit 事件调用 pollProgress() 函数,开始轮询上传进度。

@WebServlet("/upload-progress")
public class UploadProgressServlet extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    HttpSession session = req.getSession();
    UploadProgress progress = (UploadProgress) session.getAttribute("uploadProgress");
    if (progress == null) {
      resp.getWriter().print("");
      return;
    }
    progress.updateStatus();
    String jsonString = progress.toJsonString();
    resp.setContentType("application/json");
    resp.setCharacterEncoding("UTF-8");
    resp.getWriter().print(jsonString);
  }
}

在之前的 UploadServlet 中,我们可以通过 HttpSession 把 UploadProgress 对象存储在 session 中,这样 UploadProgressServlet 可以在上传之外的任何时间获取到上传的进度,从而实现精确的轮询。

以下是 UploadProgress 的定义:

public class UploadProgress {
  private final long totalSize;
  private long uploadedSize;
  private String status;

  public UploadProgress(long totalSize) {
    this.totalSize = totalSize;
    this.uploadedSize = 0;
    this.status = "IN_PROGRESS";
  }

  public synchronized void addUploadedSize(long size) {
    uploadedSize += size;
  }

  public synchronized void updateStatus() {
    if (uploadedSize >= totalSize) {
      status = "COMPLETED";
    } else if (status.equals("IN_PROGRESS")) {
      status = "IN_PROGRESS";
    } else {
      status = "FAILED";
    }
  }

  public float getPercent() {
    return uploadedSize * 100.0F / totalSize;
  }

  public synchronized String toJsonString() {
    return String.format("{\"percent\": %.2f, \"status\": \"%s\"}", getPercent(), status);
  }
}

这个 UploadProgress 类,可以保存上传总大小、已上传大小、状态(IN_PROGRESS、COMPLETED、FAILED),以及提供一些操作方法,如更新已上传大小、更新状态、计算上传百分比和将 UploadProgress 对象转成 JSON 字符串等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Jsp+Servlet实现文件上传下载 文件上传(一) - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • Maven 项目用Assembly打包可执行jar包的方法

    下面是详细的“Maven 项目用 Assembly 打包可执行 jar 包的方法”的攻略: 一、前提条件 已安装 Maven 并配置环境变量 已经有一个 Maven 项目 二、添加 Assembly 插件到 Maven 项目中 在项目的 pom.xml 文件中添加以下插件配置: <build> <plugins> <plugin…

    Java 2023年6月2日
    00
  • Java的Struts框架报错“DuplicateDefinitionException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“DuplicateDefinitionException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中有重复的定义,则可能会出现此。在这种情况下,需要检查配置文件以解决此问题。 类加载问题:如果类加载器无法加载所需的类,则可能会出现此。在这种情况下,需要检查类路径以解决此问题。 以下是两个实例…

    Java 2023年5月5日
    00
  • 页面向下滚动ajax获取数据的实现方法(兼容手机)

    实现页面向下滚动 AJAX 获取数据的方法,常用于网站无限滚动加载更多内容的功能实现。下面是实现此功能的完整攻略: 技术选型 实现页面向下滚动 AJAX 获取数据,需要使用前端技术和后端技术协同完成。前端技术主要使用 JavaScript 和 jQuery,后端技术可以选择 PHP、Java、Python等。 实现步骤 确定页面上需要进行下拉刷新的区域,一般…

    Java 2023年6月16日
    00
  • 详解Spring Data JPA中Repository的接口查询方法

    我尽力详细讲解一下“详解Spring Data JPA中Repository的接口查询方法”的攻略。 前言 Spring Data JPA作为一个数据访问框架,是Spring框架家族中的一员,它在JPA规范的基础上简化了数据访问层的代码,提供了很多便捷的查询方法,极大地提高了开发的效率。其中,Repository的接口查询方法就是Spring Data JP…

    Java 2023年6月3日
    00
  • springboot实现学生管理系统

    实现学生管理系统是一个常见的Web开发入门项目。下面我将基于Spring Boot框架,讲解如何实现一个简单的学生管理系统。 1. 环境准备 在开始之前,需要准备好以下软件或工具: JDK 1.8 或以上版本 IntelliJ IDEA 或其他Java开发工具 MySQL 数据库 Maven 依赖管理工具 2. Spring Boot 项目初始化 在 Int…

    Java 2023年5月15日
    00
  • SpringBoot YAML语法基础详细整理

    YAML是一种轻量级的数据序列化格式,常用于配置文件中。Spring Boot支持使用YAML格式的配置文件,以下是Spring Boot YAML语法基础的详细整理: 1. 基本语法 1.1 键值对 使用冒号(:)表示键值对,键和值之间用空格隔开。 key: value 1.2 列表 使用短横线(-)表示列表,每个元素占一行。 – item1 – item…

    Java 2023年5月14日
    00
  • js获取input标签的输入值实现代码

    JS获取input标签的输入值实现代码 在前端开发中,我们常常需要获取页面上输入框(input)的值,并使用该值来进行一些操作。本文将介绍如何在JavaScript中获取input标签的输入值,并提供两个示例说明。 1. 标准的input输入框 要获取标准的input输入框(即type为text、password、email等类型的输入框)的值,我们可以使用…

    Java 2023年6月15日
    00
  • Java Apache Commons报错“ZipUnsupportMethodException”的原因与解决方法

    “DuplicateActionException”是Java的Struts框架中的一个异常,通常由以下原因之一引起: Action重复:如果存在重复的Action,则可能会出现此异常。例如,可能会在配置文件中定义两个名称相同的Action。 以下是两个实例: 例1 如果存在重复的Action,则可以尝试更改Action名称以解决此问题。例如,在Struts…

    Java 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部