美文网首页
92、【JavaEE】【Servlet 与 JSP】文件上传

92、【JavaEE】【Servlet 与 JSP】文件上传

作者: yscyber | 来源:发表于2021-10-11 05:02 被阅读0次

    1、概述

    • 均是简易案例。

    • 后端使用的第三方库是:Apache Commons FileUpload、Apache Commons IO

    2、HTML 原生提交

    2.1、单个文件

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>File Upload</title>
    </head>
    <body>
    <form method="post" enctype="multipart/form-data" action="http://localhost:8080/receive-data/receive/file-upload/1">
        <input type="text" name="my_text" autocomplete="false" />
        <input type="file" name="my_file" />
        <input type="submit" value="提交" />
    </form>
    </body>
    </html>
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.commons.io.IOUtils;
    
    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 java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    @WebServlet(name = "FileUploadServlet1", urlPatterns = "/receive/file-upload/1")
    public class FileUploadServlet1 extends HttpServlet {
    
        private static final String CHARSET_ENCODING = "UTF-8";
    
        private static final long UPLOAD_FILE_MAX_BYTES = 5 * 1024 * 1024;
    
        private static final String UPLOAD_FILE_TARGET_PATH = "E:\\";
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding(CHARSET_ENCODING);
            response.setCharacterEncoding(CHARSET_ENCODING);
    
            try {
                // 1. Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();
    
                // 2. Create a new file upload handler
                ServletFileUpload uploadHandler = new ServletFileUpload(factory);
    
                // 3. Set constraints (约束)
    
                // 文件名编码
                uploadHandler.setHeaderEncoding(CHARSET_ENCODING);
                // 文件最大不超过 5MB
                // 单位是字节
                uploadHandler.setFileSizeMax(UPLOAD_FILE_MAX_BYTES);
    
                // 4. Parse the request, get a item list parsed from the form
                List<FileItem> formItemList = uploadHandler.parseRequest(request);
    
                // 5. Process
                for (FileItem item : formItemList) {
                    if (item.isFormField()) {
                        // item.isFormField() == false
                        // item is not a file
                        String fieldName = item.getFieldName();
                        String value = item.getString(CHARSET_ENCODING);
                        System.out.println(fieldName + "=" + value);
                    } else {
                        // item.isFormField() == true
                        // item is a file
                        String fieldName = item.getFieldName();
                        String fileName = item.getName();
                        System.out.println(fieldName + "=" + fileName);
    
                        String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + fileName.substring(fileName.lastIndexOf("."));
                        InputStream in = item.getInputStream();
                        FileOutputStream fos = new FileOutputStream(UPLOAD_FILE_TARGET_PATH + newFileName);
                        IOUtils.copy(in, fos);
                        if (fos != null) {
                            fos.close();
                        }
                        if (in != null) {
                            in.close();
                        }
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    2.2、多个文件 — 使用一个<input type="file" multiple />实现

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>File Upload</title>
    </head>
    <body>
    <form method="post" enctype="multipart/form-data" action="http://localhost:8080/receive-data/receive/file-upload/2">
        <input type="text" name="my_text" autocomplete="false" />
        <input type="file" name="my_file" multiple />
        <input type="submit" value="提交" />
    </form>
    </body>
    </html>
    
    // 后端代码没有变化
    
    • “后端代码没有变化”的原因是:按照常规理解,每一个<input />中的内容最终在 HTTP 请求报文的报文主体中被boundary分隔,第三方库会根据boundary切分字节流。尽管多个文件因为multiple属性被写在了一个<input type="file"/>中,但是最终形成的 HTTP 请求报文中,一个<input />中的多个文件是照常被boundary分隔开的(只不过name相同罢了)。HTTP 请求报文:
    
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywQ0kklBQk2mrySAH
    
    
    ------WebKitFormBoundarywQ0kklBQk2mrySAH
    Content-Disposition: form-data; name="my_text"
    
    ₩ネム¥メフ¦ᄑᅠ
    ------WebKitFormBoundarywQ0kklBQk2mrySAH
    Content-Disposition: form-data; name="my_file"; filename="1.pdf"
    Content-Type: application/pdf
    
    
    ------WebKitFormBoundarywQ0kklBQk2mrySAH
    Content-Disposition: form-data; name="my_file"; filename="2.pdf"
    Content-Type: application/pdf
    
    
    ------WebKitFormBoundarywQ0kklBQk2mrySAH--
    

    2.3、多个文件 — 使用多个<input type="file" />实现

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>File Upload</title>
    </head>
    <body>
    <form method="post" enctype="multipart/form-data" action="http://localhost:8080/receive-data/receive/file-upload/2">
        <input type="text" name="my_text" autocomplete="false" />
        <input type="file" name="my_file1" />
        <input type="file" name="my_file2" />
        <input type="submit" value="提交" />
    </form>
    </body>
    </html>
    
    // 后端代码没有变化
    

    3、jQuery Ajax 提交

    3.1、<input type="file" />

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>File Upload</title>
    </head>
    <body>
    <form enctype="multipart/form-data">
        <input type="text" name="my_text" id="my_text" autocomplete="false" />
        <br />
        <br />
        <input type="file" name="my_file1" id="my_file1" />
        <br />
        <br />
        <input type="file" name="my_file2" id="my_file2" />
        <br />
        <br />
        <input type="button" id="my_btn" value="提交" />
    </form>
    
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script>
        $("#my_btn").on('click', function() {
    
            let formData = new FormData();
    
            formData.append("myText", $("#my_text").val());
            formData.append("myFile1", $("#my_file1")[0].files[0]);
            formData.append("myFile2", $("#my_file2")[0].files[0]);
    
            $.ajax({
                url: 'http://localhost:8080/receive-data/receive/file-upload/3',
                type: 'POST',
                contentType: false,
                processData: false,
                data: formData,
    
                success: function(data, status, xhr) {
                    console.log(status);
                },
    
                error: function(xhr, status, error) {}
            });
        });
    </script>
    </body>
    </html>
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.commons.io.IOUtils;
    
    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 java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    @WebServlet(name = "FileUploadServlet3", urlPatterns = "/receive/file-upload/3")
    public class FileUploadServlet3 extends HttpServlet {
    
        private static final String CHARSET_ENCODING = "UTF-8";
    
        private static final long UPLOAD_FILE_MAX_BYTES = 5 * 1024 * 1024;
    
        private static final String UPLOAD_FILE_TARGET_PATH = "E:\\";
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding(CHARSET_ENCODING);
            response.setCharacterEncoding(CHARSET_ENCODING);
    
            try {
                // 1. Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();
    
                // 2. Create a new file upload handler
                ServletFileUpload uploadHandler = new ServletFileUpload(factory);
    
                // 3. Set constraints (约束)
    
                // 文件名编码
                uploadHandler.setHeaderEncoding(CHARSET_ENCODING);
                // 文件最大不超过 5MB
                // 单位是字节
                uploadHandler.setFileSizeMax(UPLOAD_FILE_MAX_BYTES);
    
                // 4. Parse the request, get a item list parsed from the form
                List<FileItem> formItemList = uploadHandler.parseRequest(request);
    
                // 5. Process
                for (FileItem item : formItemList) {
                    if (item.isFormField()) {
                        // item.isFormField() == false
                        // item is not a file
                        String fieldName = item.getFieldName();
                        String value = item.getString(CHARSET_ENCODING);
                        System.out.println(fieldName + "=" + value);
                    } else {
    
                        // item.isFormField() == true
                        // item is a file
                        String fieldName = item.getFieldName();
                        String fileName = item.getName();
                        System.out.println(fieldName + "=" + fileName);
    
                        String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + fileName.substring(fileName.lastIndexOf("."));
                        InputStream in = item.getInputStream();
                        FileOutputStream fos = new FileOutputStream(UPLOAD_FILE_TARGET_PATH + newFileName);
                        IOUtils.copy(in, fos);
                        if (fos != null) {
                            fos.close();
                        }
                        if (in != null) {
                            in.close();
                        }
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    3.1、<input type="file" multiple />

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <title>File Upload</title>
    </head>
    <body>
    <form enctype="multipart/form-data">
        <input type="text" name="my_text" id="my_text" autocomplete="false" />
        <br />
        <br />
        <input type="file" name="my_file" id="my_file" multiple />
        <br />
        <br />
        <input type="button" id="my_btn" value="提交" />
    </form>
    
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script>
        $("#my_btn").on('click', function() {
    
            let formData = new FormData();
    
            formData.append("myText", $("#my_text").val());
    
            let fileArr = $("#my_file")[0].files;
            for (let i = 0; i < fileArr.length; i++) {
                formData.append("myFile", fileArr[i]);
            }
    
            $.ajax({
                url: 'http://localhost:8080/receive-data/receive/file-upload/3',
                type: 'POST',
                contentType: false,
                processData: false,
                data: formData,
    
                success: function(data, status, xhr) {
                    console.log(status);
                },
    
                error: function(xhr, status, error) {}
            });
        });
    </script>
    </body>
    </html>
    
    // 后端代码不用变
    
    • 需要注意的是,FormDataappend方法,FormData虽然像 Java 中的 Map,但是FormData中允许存在重复的“键”,所以当使用append方法时,“键”相同也不存在被覆盖的问题。
      当然,具体使用上是否允许“重复”存在,取决于开发约定。

    相关文章

      网友评论

          本文标题:92、【JavaEE】【Servlet 与 JSP】文件上传

          本文链接:https://www.haomeiwen.com/subject/byqtoltx.html