Java Servlet Technology - 上传文件

Java Servlet Technology

Uploading Files with Java Servlet Technology

Supporting file uploads is a very basic and common requirement for many web applications. In prior versions of the Servlet specification, implementing file upload required the use of external libraries or complex input processing. The Java Servlet specification now helps to provide a viable solution to the problem in a generic and portable way. Java Servlet technology now supports file upload out of the box, so any web container that implements the specification can parse multipart requests and make mime attachments available through the HttpServletRequest object.

A new annotation, javax.servlet.annotation.MultipartConfig, is used to indicate that the servlet on which it is declared expects requests to be made using the multipart/form-data MIME type. Servlets that are annotated with @MultipartConfig can retrieve the Part components of a given multipart/form-data request by calling the request.getPart(String name) or request.getParts() method.

The @MultipartConfig Annotation

The @MultipartConfig annotation supports the following optional attributes.

  • location: An absolute path to a directory on the file system. The location attribute does not support a path relative to the application context. This location is used to store files temporarily while the parts are processed or when the size of the file exceeds the specified fileSizeThreshold setting. The default location is "".
  • fileSizeThreshold: The file size in bytes after which the file will be temporarily stored on disk. The default size is 0 bytes.
  • MaxFileSize: The maximum size allowed for uploaded files, in bytes. If the size of any uploaded file is greater than this size, the web container will throw an exception (IllegalStateException). The default size is unlimited.
  • maxRequestSize: The maximum size allowed for a multipart/form-data request, in bytes. The web container will throw an exception if the overall size of all uploaded files exceeds this threshold. The default size is unlimited.

For, example, the @MultipartConfig annotation could be constructed as follows:

@MultipartConfig(location="/tmp", fileSizeThreshold=1024*1024,
    maxFileSize=1024*1024*5, maxRequestSize=1024*1024*5*5)

Instead of using the @MultipartConfig annotation to hard-code these attributes in your file upload servlet, you could add the following as a child element of the servlet configuration element in the web.xml file:

<multipart-config>
    <location>/tmp</location>
    <max-file-size>20848820</max-file-size>
    <max-request-size>418018841</max-request-size>
    <file-size-threshold>1048576</file-size-threshold>
</multipart-config>

The getParts and getPart Methods

The Servlet specification supports two additional HttpServletRequest methods:

  • Collection<Part> getParts()
  • Part getPart(String name)

The request.getParts() method returns collections of all Part objects. If you have more than one input of type file, multiple Part objects are returned. Because Part objects are named, the getPart(String name) method can be used to access a particular Part. Alternatively, the getParts() method, which returns an Iterable<Part>, can be used to get an Iterator over all the Part objects.

The javax.servlet.http.Part interface is a simple one, providing methods that allow introspection of each Part. The methods do the following:

  • Retrieve the name, size, and content-type of the Part
  • Query the headers submitted with a Part
  • Delete a Part
  • Write a Part out to disk

For example, the Part interface provides the write(String filename) method to write the file with the specified name. The file can then be saved in the directory that is specified with the location attribute of the @MultipartConfig annotation or, in the case of the fileupload example, in the location specified by the Destination field in the form.

实践

环境

操作系统:

Windows 10 x64

集成开发环境:

Eclipse IDE for Enterprise Java and Web Developers (includes Incubating components)

Version: 2021-09 (4.21.0)

Build id: 20210910-1417

服务器:

apache-tomcat-9.0.55

客户端:

谷歌浏览器:版本 96.0.4664.93(正式版本) (64 位)

新建项目

新建 Dynamic Web Project

在这里插入图片描述

上传单个文件

新建 FileUploadServlet 类,继承自 HttpServlet

package com.mk.servlet;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

@WebServlet(urlPatterns = "/upload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    
    private static final Logger logger = Logger.getLogger(FileUploadServlet.class.getCanonicalName());
    
    private static final String path = "D:/F/file";
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        
        Part part = request.getPart("file");
        String submittedFileName = part.getSubmittedFileName();
        
        logger.log(Level.INFO, "Name: {0}", part.getName());
        logger.log(Level.INFO, "Submitted File Name: {0}", submittedFileName);
        logger.log(Level.INFO, "Size: {0}", part.getSize());
        
        InputStream in = part.getInputStream();
        OutputStream out = new FileOutputStream(new File(path + File.separator + submittedFileName));
        
        int length = 0;
        byte[] bytes = new byte[1024];
        while((length = in.read(bytes)) != -1) {
            out.write(bytes, 0, length);
        }
        
        logger.log(Level.INFO, "File {0} being uploaded to {1}", new Object[] {submittedFileName, path});
        
        close(out);
        close(in);
    }
    
    public static void close(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

基于表单上传单个文件

src/main/webapp/index.html 文件:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
		<form method="POST" action="upload" enctype="multipart/form-data">
			<input type="file" name="file" />
			<br />
			<input type="submit" value="Upload" />
		</form>
	</body>
</html>

测试

启动服务器,访问 http://localhost:8080/hello-servlet/index.html,选择文件并上传:

在这里插入图片描述

控制台输出:

12月 23, 2021 7:41:49 下午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 23, 2021 7:41:49 下午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: 冬兵.png
12月 23, 2021 7:41:49 下午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 506,421
12月 23, 2021 7:41:49 下午 com.mk.servlet.FileUploadServlet doPost
信息: File 冬兵.png being uploaded to D:/F/file

基于 AJAX 上传单个文件

编辑 src/main/webapp/index.html 文件,使用 AJAX 上传单个文件:


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>上传单个文件</title>
    </head>
    <body>
        <input type="file" accept="*.*" />

        <script type="text/javascript">
            window.onload = (event) => {
                const input = document.querySelector("input[type=file]");
                
                input.onchange = (event) => {
                    const files = event.target.files;
                    
                    if (files.length > 0) {
                        const formData = new FormData();
                        formData.append("file", files[0]);
                        
                        const xhr = new XMLHttpRequest()
                        xhr.addEventListener("load", function(event) {
//                             console.log(event)
                			const DONE = 4
                            if (xhr.readyState == DONE && xhr.status == 200) {
                                console.log(xhr)
                                console.log(xhr.response)
                            }
                        })
                        xhr.open("POST", "/hello-servlet/upload", true)
                        xhr.responseType = "json";
                        xhr.send(formData);
                    }
                }
            }
		</script>
    </body>
</html>

测试

启动服务器,访问 http://localhost:8080/hello-servlet/index.html,选择文件并上传:

在这里插入图片描述

控制台输出:

12月 24, 2021 10:44:25 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 10:44:25 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: 冬兵.jpg
12月 24, 2021 10:44:25 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 34,394
12月 24, 2021 10:44:25 上午 com.mk.servlet.FileUploadServlet doPost
信息: File 冬兵.jpg being uploaded to D:/F/file

上传多个文件

编辑 FileUploadServlet 类,遍历用户上传的多个文件:

package com.mk.servlet;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

@WebServlet(urlPatterns = "/upload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    
    private static final Logger logger = Logger.getLogger(FileUploadServlet.class.getCanonicalName());
    
    private static final String path = "D:/F/file"; // 文件的存储位置
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        
        Collection<Part> parts = request.getParts();
        Iterator<Part> iterator = parts.iterator();
        while (iterator.hasNext()) {
            Part part = iterator.next();
            
            String submittedFileName = part.getSubmittedFileName();
            
            logger.log(Level.INFO, "Name: {0}", part.getName());
            logger.log(Level.INFO, "Submitted File Name: {0}", submittedFileName);
            logger.log(Level.INFO, "Size: {0}", part.getSize());
            
            InputStream in = part.getInputStream();
            OutputStream out = new FileOutputStream(new File(path + File.separator + submittedFileName));
            
            byte[] buffer = new byte[1024];
            for (int length = in.read(buffer); length != -1; length = in.read(buffer)) {
                out.write(buffer, 0, length);
            }
            
            logger.log(Level.INFO, "File {0} being uploaded to {1}", new Object[] {submittedFileName, path});
            
            close(out);
            close(in);
        }
    }
    
    public static void close(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

基于表单上传多个文件

编辑 src/main/webapp/index.html 文件,使用表单上传多个文件:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>基于表单上传多个文件</title>
    </head>
    <body>
		<form method="POST" action="upload" enctype="multipart/form-data">
			<!-- 通过使用 multiple 属性,允许用户选择多个文件 -->
			<input type="file" name="file" multiple />
			<br />
			<input type="submit" value="上传" />
		</form>
	</body>
</html>

测试

启动服务器,访问 http://localhost:8080/hello-servlet/index.html,选择多个文件并上传:

在这里插入图片描述

控制台输出:

12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: OHR.MotherCheetah_ZH-CN6992630248_1920x1080.jpg
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 341,567
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: File OHR.MotherCheetah_ZH-CN6992630248_1920x1080.jpg being uploaded to D:/F/file
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: th.jpg
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 338,455
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: File th.jpg being uploaded to D:/F/file
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: 冬兵.jpg
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 34,394
12月 24, 2021 11:28:10 上午 com.mk.servlet.FileUploadServlet doPost
信息: File 冬兵.jpg being uploaded to D:/F/file

基于 AJAX 上传多个文件

编辑 src/main/webapp/index.html 文件,使用 AJAX 上传多个文件:


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>基于 AJAX 上传多个文件</title>
    </head>
    <body>
        <input type="file" accept="*.*" multiple />

        <script type="text/javascript">
            window.onload = (event) => {
                const input = document.querySelector("input[type=file]");
                
                input.onchange = (event) => {
                    const files = event.target.files;
                    
                    if (files.length > 0) {
                        const formData = new FormData();
                    	for (let i = 0; i < files.length; i++) {
                    		const file = files[i];
                            console.log(file);
                            formData.append("file", files[i]);
                    	}
                        
                        const xhr = new XMLHttpRequest();
                        xhr.addEventListener("load", function(event) {
//                             console.log(event)
                			const DONE = 4;
                            if (xhr.readyState == DONE && xhr.status == 200) {
                                console.log(xhr);
                                console.log(xhr.response);
                            }
                        })
                        xhr.open("POST", "/hello-servlet/upload", true);
                        xhr.send(formData);
                    }
                }
            }
		</script>
    </body>
</html>

测试

启动服务器,访问 http://localhost:8080/hello-servlet/index.html,选择多个文件并上传:

在这里插入图片描述

控制台输出:

12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: OHR.DenaliDall_ZH-CN9952652691_1920x1080.jpg
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 343,674
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: File OHR.DenaliDall_ZH-CN9952652691_1920x1080.jpg being uploaded to D:/F/file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: OHR.MistyTor_ZH-CN7520952555_1920x1080.jpg
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 344,134
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: File OHR.MistyTor_ZH-CN7520952555_1920x1080.jpg being uploaded to D:/F/file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: OHR.MotherCheetah_ZH-CN6992630248_1920x1080.jpg
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 341,567
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: File OHR.MotherCheetah_ZH-CN6992630248_1920x1080.jpg being uploaded to D:/F/file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: th.jpg
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 338,455
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: File th.jpg being uploaded to D:/F/file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Name: file
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Submitted File Name: 冬兵.jpg
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: Size: 34,394
12月 24, 2021 11:31:31 上午 com.mk.servlet.FileUploadServlet doPost
信息: File 冬兵.jpg being uploaded to D:/F/file

参考

Java Servlet Technology - Uploading Files with Java Servlet Technology

Java Servlet Technology - The fileupload Example Application

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值