tomcat上传超过限制文件大小报异常而不能正常转发的bug

1、上传示例的源码

【index.jsp】

文件的上传

${requestScope.errorMsg}

用户名:

文件1:

文件2:

文件3:

【success.jsp】

文件上传成功!

返回上传页面

【FileUploadServlet】

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
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.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class FileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 创建工厂实例
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 创建解析器实例
        ServletFileUpload fileUpload = new ServletFileUpload(factory);

        // 设置单个文件大小1Kb【单位字节】
        fileUpload.setFileSizeMax(1024);
        // 设置多个文件大小2Kb【单位字节】
        fileUpload.setSizeMax(2 * 1024);

        try {
            // 解析请求获取每一个表单项
            List fileItems = fileUpload.parseRequest(request);

            int size = fileItems.size();
            for (int i = 0; i < size; i++) {
                FileItem fileItem = fileItems.get(i);

                // 获取表单项的name属性值
                String fieldName = fileItem.getFieldName();

                // 是否是一个文本输入框
                boolean formField = fileItem.isFormField();
                if (formField) {
                    // 获取表单value属性值,以UTF-8来解码
                    String value = fileItem.getString("UTF-8");

                    // 没有输入内容
                    if ("".equals(value)) {
                        request.setAttribute("errorMsg", "请输入内容!");
                        request.getRequestDispatcher("/index.jsp").forward(request, response);
                        return;
                    }

                    System.out.println("表单项name属性:" + fieldName);
                    System.out.println("用户输入的内容:" + value);
                } else {
                    System.out.println("表单name属性值:" + fieldName);

                    // 获取文件名
                    String fileName = fileItem.getName();
                    // 获取文件大小(单位字节)
                    long fileSize = fileItem.getSize();
                    // 获取文件的MIME类型
                    String fileType = fileItem.getContentType();

                    // 没有上传文件
                    if (0 == fileSize) {
                        request.setAttribute("errorMsg", "请上传文件!");
                        request.getRequestDispatcher("/index.jsp").forward(request, response);
                        return;
                    }

                    System.out.println("文件名:" + fileName);
                    System.out.println("文件大小:" + fileSize + "字节");
                    System.out.println("文件MIME类型:" + fileType);

                    String uploadPath = "/upload";
                    // 上传到服务器的路径的绝对路径
                    uploadPath = getServletContext().getRealPath(uploadPath);
                    File uploadFile = new File(uploadPath);
                    if (!uploadFile.exists()) {
                        uploadFile.mkdirs();
                    }

                    // 兼容IE5、IE6获取到的文件名是绝对路径
                    fileName = fileName.substring(fileName.lastIndexOf(File.separator) + 1);

                    // 生成UUID
                    String uuid = UUID.randomUUID().toString().replace("-", "");
                    // 唯一的文件名
                    uploadPath = uploadPath + File.separator + uuid + "_" + fileName;

                    uploadFile = new File(uploadPath);

                    // 写到服务器硬盘上
                    fileItem.write(uploadFile);

                }

            }

            // 成功,跳转到成功页面
            response.sendRedirect(request.getContextPath() + "/success.jsp");

        } catch (FileSizeLimitExceededException e) {
            request.setAttribute("errorMsg", "单个文件最大1Kb");
            request.getRequestDispatcher("/index.jsp").forward(request, response);

            System.out.println("单个文件错误信息:" + e.getMessage());
        } catch (SizeLimitExceededException e) {
            request.setAttribute("errorMsg", "多个文件最大2Kb");
            request.getRequestDispatcher("/index.jsp").forward(request, response);

            System.out.println("多个文件错误信息:" + e.getMessage());
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

【Tips】

这里限制上传的单个文件最大1Kb,多个文件2Kb

2、错误的触发

当上传 3.53 MB (3,706,535 字节)大小的文件时,catch中的转发没有正常执行
并且浏览器报错
tomcat上传超过限制文件大小报异常而不能正常转发的bug_第1张图片

3、错误的原因

用户上传超过指定的单个文件大小,会报异常:
FileSizeLimitExceededException

超过多个文件大小,会报异常:
SizeLimitExceededException

在catch这些异常时,有时会给用户以响应,通过request域设置错误信息,但是当用户上传的文件超过限制的大小过大时,并不会转发,这是tomcat的bug:

    https://bz.apache.org/bugzilla/show_bug.cgi?id=57438

4、错误解决办法

使用低版本的tomcat

亲测tomcat7.0.39没有问题【Chrome、Filefox、IE10】

下载地址:
    http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.39/bin/

源码:
    http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.39/src/

你可能感兴趣的:(JavaWeb)