java基于servlet实现文件上传功能解析

接下来我将详细讲解Java基于Servlet实现文件上传功能的完整攻略。该攻略分为以下几个步骤:

  1. 在HTML页面中添加文件上传表单
  2. 编写Servlet来处理文件上传请求
  3. 使用Apache的文件上传组件来解析文件上传请求
  4. 保存文件到指定位置并返回上传结果给用户

下面就来详细介绍这些步骤。

1. 在HTML页面中添加文件上传表单

首先,在你的HTML页面中添加一个文件上传表单,如下所示:

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

其中,action属性指定表单提交的目标URL,方法是POST,enctype属性是必要的,因为它指定要使用的编码类型,这里是multipart/form-data类型,这种类型可以支持文件上传。

2. 编写Servlet来处理文件上传请求

然后,我们需要编写一个Servlet来处理用户的文件上传请求。首先,需要在web.xml文件中添加一个Servlet的映射。

<servlet>
    <servlet-name>uploadServlet</servlet-name>
    <servlet-class>com.example.UploadServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>uploadServlet</servlet-name>
    <url-pattern>/upload</url-pattern>
</servlet-mapping>

其中,servlet-name指定了Servlet的名称,servlet-class则指定了Servlet的类路径。同时,servlet-mapping则用于将URL请求映射到Servlet。

接下来,我们就需要实现com.example.UploadServlet类,代码示例如下:

package com.example;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

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

    private static final long serialVersionUID = 1L;

    private static final String UPLOAD_DIRECTORY = "uploads"; // 上传目录
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50; // 50MB

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 检查请求是否为multipart/form-data
        if (!ServletFileUpload.isMultipartContent(request)) {
            // 如果不是则停止
            PrintWriter writer = response.getWriter();
            writer.println("Error: 表单必须包含 enctype=multipart/form-data");
            writer.flush();
            return;
        }

        // 配置上传参数
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存临界值
        factory.setSizeThreshold(MEMORY_THRESHOLD);
        // 设置临时存储目录
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

        ServletFileUpload upload = new ServletFileUpload(factory);

        // 设置最大文件上传值
        upload.setFileSizeMax(MAX_FILE_SIZE);

        // 设置最大请求值 (包含文件和表单数据)
        upload.setSizeMax(MAX_REQUEST_SIZE);

        // 中文处理
        upload.setHeaderEncoding("UTF-8"); 

        // 构造临时路径来存储上传的文件
        // 这个路径相对当前应用的目录
        String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;

        // 如果目录不存在则创建
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }

        try {
            // 解析请求的内容提取文件数据
            @SuppressWarnings("unchecked")
            List<FileItem> formItems = upload.parseRequest(request);

            if (formItems != null && formItems.size() > 0) {
                // 迭代表单数据
                for (FileItem item : formItems) {
                    // 处理不在表单中的字段
                    if (!item.isFormField()) {
                        String fileName = new File(item.getName()).getName();
                        String filePath = uploadPath + File.separator + fileName;
                        File storeFile = new File(filePath);

                        // 保存文件到硬盘
                        item.write(storeFile);
                        request.setAttribute("message", "文件上传成功!");
                    }
                }
            }
        } catch (Exception ex) {
            request.setAttribute("message", "发生错误: " + ex.getMessage());
        }

        // 跳转到 message.jsp
        getServletContext().getRequestDispatcher("/message.jsp").forward(request, response);
    }
}

3. 使用Apache的文件上传组件来解析文件上传请求

上述代码使用了Apache的文件上传组件,org.apache.commons.fileupload。该组件提供了一个非常方便的API,可以处理文件上传请求。具体来说,以下是该攻略的一些关键部分:

  • DiskFileItemFactory: 文件上传的临时文件存储,它的默认构造函数将全部的二进制数据存储在内存,使用过多内存,因此使用setDefaultRepository将一部分存在硬盘上,该类还提供一个API来修改这个允许在内存中存储的数据的量。
  • ServletFileUpload: 文件上传的辅助类。ServletFileUpload包含一个FileItemFactory,它负责管理上传文件的存储,并将这些文件项存储在内存,或临时存储在磁盘中。
  • 构造实际的路径,并创建一个目录以存储上传文件。

在获取参数之前,我们将检查请求是否为multipart/form-data,这是我们是否真正处理文件上传的标志。我们也设置了一些UploadLimits来限制用户的上传大小。

然后,我们解析请求的文件和传输数据。如果是文件数据,我们将其保存到服务器的文件系统中。

4. 保存文件到指定位置并返回上传结果给用户

处理完文件上传请求后,我们需要将上传结果返回给用户,通常是返回一个确认消息。这时,我们需要将结果存储到request的属性中,然后使用JSP Page显示。

可以创建一个名为message.jsp的页面,其中包含以下代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>文件上传结果</title>
    </head>
    <body>
        <h1>文件上传结果</h1>
        <p>${message}</p>
    </body>
</html>

其中,${message}表示之前在Servlet中设置的message属性值,即文件上传结果。

至此,Java基于Servlet实现文件上传功能的完整攻略就介绍完了。

示例1

假设我们的项目名为FileUploadDemo,我们可以将以下示例代码保存为.jsp文件,然后部署到我们的Tomcat Web服务器上:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>文件上传示例</title>
    </head>
    <body>
        <h1>文件上传示例</h1>
        <form action="http://localhost:8080/FileUploadDemo/upload" method="post" enctype="multipart/form-data">
            <label for="file">文件:</label> <input type="file" name="file" id="file"><br>
            <input type="submit" name="submit" value="上传">
        </form>
    </body>
</html>

注意,文件上传表单的action属性应该设置为我们之前配置的上传Servlet路径,即/upload

示例2

除此之外,我们还可以使用Java内置的HttpURLConnection类来实现文件上传,示例代码如下:

package com.example;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class FileUploader {

    public static void main(String[] args) throws Exception {
        String serverUrl = "http://localhost:8080/FileUploadDemo/upload";
        String filePath = "/Users/user1/Documents/Book.pdf";

        File uploadFile = new File(filePath);
        String boundary = "-----------------------------" + System.currentTimeMillis();

        HttpURLConnection connection = (HttpURLConnection) new URL(serverUrl).openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        connection.setRequestProperty("User-Agent", "Java File Uploader/1.0");

        DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
        outputStream.writeBytes("--" + boundary + "\r\n");
        outputStream.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + uploadFile.getName() + "\"\r\n");
        outputStream.writeBytes("Content-Type: application/octet-stream\r\n\r\n");

        FileInputStream inputStream = new FileInputStream(uploadFile);
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.writeBytes("\r\n--" + boundary + "--\r\n");

        inputStream.close();
        outputStream.flush();
        outputStream.close();

        System.out.println(connection.getResponseCode());
        System.out.println(connection.getResponseMessage());
    }
}

这个示例代码读取本地文件/Users/user1/Documents/Book.pdf并将其上传到指定的Web服务器。它使用了HttpURLConnection类来做Http传输并指定了请求方式POST、上传文件的Content-Type以及POST数据的分隔符。文件内容则通过DataOutputStream来写入RequestBody之内。值得注意的是,文件数据写入完成后,也要加上一个分隔符和标志结束。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java基于servlet实现文件上传功能解析 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java设计模式之java策略模式详解

    Java设计模式之Java策略模式详解 什么是Java策略模式? Java策略模式是一种行为型设计模式,它定义了算法族,即一组具有相同目的和不同实现的算法,让它们之间可以相互替换。这个模式让算法的变化独立于使用算法的客户端,从而实现算法行为的变化而无需更改使用算法的客户端。 Java策略模式的三个角色 Java策略模式一般涉及到如下三个角色: Context…

    Java 2023年5月19日
    00
  • jvm中指定时区信息user.timezone问题及解决方式

    关于JVM中指定时区信息的问题与解决方式,我们可以分以下几步来进行讲解: 1. 了解时区 时区是指地球上划分为24个时区的区域。它是以经线划分的,每个时区都跨度15°,从东向西依次为UTC+12、UTC+11、UTC+10、……、UTC-11、UTC-12。 2. JVM中的时区 在JVM运行中,时区信息是通过System类中的user.timezone属性…

    Java 2023年5月20日
    00
  • Java中BigDecimal类的简单用法

    Java中BigDecimal类的简单用法 什么是BigDecimal? BigDecimal是Java中的一个数学类,它主要用于处理高精度的浮点数运算,并避免了普通float和double数值的精度损失问题。在需要极高精度计算的场景中,BigDecimal可以起到至关重要的作用。 如何使用BigDecimal? 创建BigDecimal对象 我们可以使用B…

    Java 2023年5月26日
    00
  • java读取excel文件并复制(copy)文件到指定目录示例

    针对“java读取excel文件并复制(copy)文件到指定目录示例”,我为您提供以下攻略: 一、读取Excel文件 读取Excel文件需要用到Java中的POI工具包,具体的操作步骤如下: 添加依赖包 在Maven的pom.xml文件中添加如下的依赖: <dependency> <groupId>org.apache.poi<…

    Java 2023年5月19日
    00
  • 一个合格的程序员应该读过哪些书(偏java)

    一个合格的程序员应该读过哪些书(偏 Java) 作为一名合格的程序员,阅读技术书籍是必不可少的,本文将为大家介绍几本值得程序员阅读的 Java 书籍。 基础篇 《Java核心技术 卷1+卷2》 这是 Java 开发者学习 Java 语言核心知识的第一本书,它的第一卷全面讲解了 Java 语言中的基础概念和关键技术,第二卷则着重介绍 Java 的高级特性。无论…

    Java 2023年5月20日
    00
  • SpringBoot整合Druid数据源过程详解

    以下是SpringBoot整合Druid数据源的详细攻略。 准备工作 引入相关依赖 为了使用Druid数据源,我们需要在pom.xml文件中添加以下依赖: <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-star…

    Java 2023年5月20日
    00
  • SpringBoot集成内存数据库Sqlite的实践

    下面我将为您详细讲解“SpringBoot集成内存数据库Sqlite的实践”的完整攻略。 1. 关于Sqlite Sqlite是一种轻量级的关系型数据库,最主要的特点是没有独立的进程,所有的数据库操作都直接在应用程序内部完成,这使得Sqlite非常适合一些较小的场景,例如移动应用或单机桌面应用等。由于Sqlite的持久化方式是基于文件的,所以它也被称为嵌入式…

    Java 2023年5月20日
    00
  • jdbc实现连接和增删改查功能

    下面我将详细讲解如何使用JDBC实现连接和增删改查功能的完整攻略,具体步骤如下: 1. 下载并导入JDBC驱动 JDBC是Java中操作关系型数据库的标准API,但是需要使用具体的数据库驱动来连接数据库。因此,在使用JDBC之前,需要下载并导入相关的JDBC驱动。 以MySQL数据库为例,可以从MySQL官方网站上下载JDBC驱动,下载地址为: https:…

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