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日

相关文章

  • java常见的字符串操作和日期操作汇总

    Java常见的字符串操作 字符串的基本操作 Java String是不可变对象,是对比较字符串最常用最简便的类,常见的字符串操作有: 字符串拼接: 使用+操作符进行字符串拼接,例如 “Hello” + “World”,结果为 “Hello World”。 使用concat()方法进行字符串拼接,例如 “Hello”.concat(” “).concat(“W…

    Java 2023年5月20日
    00
  • 了解在Flash中的编程工作

    了解在Flash中的编程工作是一个必要的过程,它可以帮助你学习如何使用Flash的编程工具来创建交互式的动画和应用程序。以下是一些步骤,可以帮助你开始学习Flash的编程工作。 步骤1:学习Flash编程语言 Flash编程语言可以使你直接控制Flash中的对象和操作。其中,ActionScript是Flash主要的编程语言。学习ActionScript可以…

    Java 2023年6月15日
    00
  • 老生常谈计算机中的编码问题(必看篇)

    老生常谈计算机中的编码问题(必看篇) 简介 计算机中的编码问题是计算机领域长期存在的老生常谈问题之一。这个问题的本质是计算机内部和外部传输的信息都需要以某种编码方式呈现,而不同的编码方式之间可能存在互相转换的问题,容易引起信息传输和解读上的困难。 常见编码方式 常见的计算机编码方式包括ASCII编码、Unicode编码和UTF-8编码等。其中: ASCII编…

    Java 2023年5月20日
    00
  • SpringBoot集成quartz实现定时任务详解

    SpringBoot集成Quartz实现定时任务详解 1. 什么是Quartz Quartz是一个开源的作业调度框架,其主要用于定时调度任务。它能够完成复杂的调度需求,如在指定时间执行任务、每天执行任务、周末执行任务等。 2. SpringBoot集成Quartz 2.1 引入依赖 我们首先需要在pom.xml文件中引入quartz和spring-boot-…

    Java 2023年5月19日
    00
  • java 中mongodb的各种操作查询的实例详解

    下面我将为您详细讲解在Java中使用MongoDB进行各种操作和查询的实例详解。 1. MongoDB介绍 MongoDB是一种基于文档的NoSQL数据库,在许多应用场景中,它都是一种非常有效的数据存储解决方案。MongoDB支持的语言众多,其中Java是其中一个主要支持的语言。在Java程序中,通过MongoDB Java驱动程序可以方便地对MongoDB…

    Java 2023年5月20日
    00
  • 简单总结Java IO中stream流的使用方法

    下面是“简单总结Java IO中stream流的使用方法”的完整攻略: 1. Java IO中的Stream流 Java IO(Input/Output)是指Java语言中的输入输出流操作,用于读取和写入数据。在Java IO中,输入输出是用Stream(流)的方式进行的。Stream流提供了InputSteam和OutputStream两个抽象类,它们是所…

    Java 2023年5月26日
    00
  • MyBatis动态SQL表达式详解

    MyBatis动态SQL是针对不同情况下需要根据不同条件动态调整SQL语句的需求而产生的一种功能,具有很强的灵活性和可读性。其中动态SQL表达式是实现动态SQL的关键,本文将解析MyBatis中动态SQL表达式的使用方法和一些示例。 什么是MyBatis动态SQL表达式 MyBatis动态SQL表达式一般用于编写可动态调整SQL的Mapper文件,可以根据不…

    Java 2023年5月19日
    00
  • JSP监听器用法分析

    JSP监听器用法分析 什么是JSP监听器 JSP监听器是监听JSP页面对象(即JspPage对象)创建、销毁、初始化、属性发生更改和请求响应等事件的一种对象。通过在这些事件发生时执行自定义逻辑进行应用程序的初始化和维护。 JSP监听器的使用 步骤一:编写JSP监听器 实现javax.servlet.jsp.JspPageListener接口。 编写在Jsp创…

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