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 2023年5月19日
    00
  • java编译时与运行时概念与实例详解

    Java编译时与运行时概念与实例详解 在Java程序员的日常工作中,熟练掌握Java编译时和运行时的概念非常重要。本文将详细介绍Java编译时和运行时的相关知识以及一些实例。 Java编译时 概念 Java编译时是指将Java源代码编译为class文件的过程。在Java程序开发中,一般先编写Java源代码,然后通过JDK中的javac命令将Java源代码编译…

    Java 2023年5月20日
    00
  • 详解SpringBoot+Thymeleaf 基于HTML5的现代模板引擎

    Sure,下面我会详细讲解“详解SpringBoot+Thymeleaf 基于HTML5的现代模板引擎”的完整攻略。 简介 Thymeleaf 是一个用于 Web 与独立环境的现代服务器端 Java 模板引擎。Thymeleaf 的主要目标是提供一种优雅和高度可维护的创建 XHTML / HTML5 的模板的方式;同时也可以非常轻松地拓展为JSP等模板引擎,…

    Java 2023年6月15日
    00
  • ServletContext中常用方法介绍

    下面是关于“ServletContext中常用方法介绍”的完整攻略。 一、ServletContext概述 在Java Web中,ServletContext表示Servlet上下文,是一个Web应用的全局上下文环境。每个Web应用都会有一个ServletContext,在应用启动的时候创建,并且在应用停止的时候销毁。 ServletContext中的信息可…

    Java 2023年6月2日
    00
  • Java模拟rank/over函数实现获取分组排名的方法详解

    Java模拟rank/over函数实现获取分组排名的方法详解 在数据处理过程中,我们常常需要获取某一列数据的分组排名。在SQL中,可以使用rank和over函数来获取。但是在Java中,在处理数据时并没有直接的rank和over函数,需要我们自己进行模拟实现。 什么是rank和over函数 rank函数:对列中的数据按照升序或降序排名,如果有相同值,则排名相…

    Java 2023年5月26日
    00
  • MyBatis传入多个参数时parameterType的写法

    MyBatis是一个Java持久层ORM框架,支持多种数据库,本质上是将SQL语句映射成Java方法调用,将Java对象映射成数据库中的记录。在使用MyBatis进行开发时,我们需要经常传入多个参数,来完成复杂的查询、插入、更新、删除等操作。这就需要我们正确设置parameterType参数来保证程序的正常运行。 1.传入多个参数时parameterType…

    Java 2023年5月20日
    00
  • js中return false(阻止)的用法

    JavaScript中的return false可以用来阻止某些事件的发生或者是提交某些表单的行为。它是常用的一种代码技巧,下面将详细讲解其用法。 一、阻止事件发生 在JavaScript中,我们经常需要对某些事件进行监听,并在事件触发时执行相应的操作。例如,在点击一个按钮时,我们可能需要执行一些操作并且阻止浏览器跳转到该按钮所指的链接。我们可以使用retu…

    Java 2023年6月15日
    00
  • Java实现纪元秒和本地日期时间互换的方法【经典实例】

    Java实现纪元秒和本地日期时间互换的方法【经典实例】 什么是纪元秒? 纪元秒是指从“1970年1月1日 00:00:00 UTC”开始计算至某一时刻之间的秒数。 纪元秒与本地日期时间的相互转换 Java提供了从纪元秒到本地日期时间和从本地日期时间到纪元秒的转换方法。这些方法都属于Java API中的java.time包。 从纪元秒到本地日期时间 Java中…

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