使用 commons-fileupload(空列表<FileItem>)通过 JSP 从本地驱动器解析文件

Parsing file from local drive via JSP using commons-fileupload (empty List<FileItem>)

我正在尝试将文件从本地驱动器 (Windows 10) 解析到 Linux 框上的服务器 运行。 servlet 低于 3.0 版本,所以我使用的是 Apache FileUpload 和 IO jar。我在尝试解析文件时遇到 2 个问题。

使用<input type = "submit" value = "Upload File" >提交目前不会提交数据所以我使用<button id="ok" onclick="document.forms[0].submit();return false;">Submit</button>.

第二个也是更严重的问题是我无法将解析后的数据上传到列表。提交表单后,列表为空。我已经注释掉了 jsp 表单中的每个方法,所以我不应该在 Apache 上传之前读取和解析请求主体(但我不确定在尝试读取文件之前如何验证主体是否为空)。我也尝试上传文本而不是文件(以检查尝试访问 windows 文件系统是否有问题)但没有成功。

也许我遗漏了一些明显的东西。你能给我一些如何解决这个问题的提示吗?谢谢

JSP(旧文件)

<%@ page language="java" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ include file="upload_function.jspf" %>
<%String pageLanguage=getLanguage(request);%>
<%@ MultipartConfig%>
<%@WebServlet("/upload")%>

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="upload.css"></link>
    </head>
    <body>
        <form action="" method="post" enctype="multipart/form-data" ></form>
            <div>
                <tr>
                    <h4>Uploaded File:</h4>
                    <%=getLocalImage(request)%>
                </tr>
            </div>

<div>
                <tr>
                    <label for=""><h4>File Upload:</h4></label>
                    <input type="file" id="image" name="image" accept="image/png, image/jpeg"  >                    
                    <input type = "submit" value = "Upload File" >          
                </tr>
            </div>

            <div>
                <tr>
                    <p>
                        <button id="ok" onclick="document.forms[0].submit();return false;">Submit</button>
                        <button id="cancel" onclick="javascript:window.close();return false;">Ok</button>
                    </p>
                </tr>
            </div>
        </form>
    </body>
</html>

JSPF(旧文件)

<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<%@ page import="javax.servlet.*" %>
<%@ page import="org.apache.commons.fileupload.disk.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.*" %>
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.io.*" %>

<%!

public String getLocalImage(HttpServletRequest request) throws ServletException, IOException 
    {
        String result = "null";
        String UPLOAD_DIRECTORY = "/final/directory/for/file/upload/";

        // Check the content
        if(ServletFileUpload.isMultipartContent(request)){
            try {
                // Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();

                // Configure a repository (to ensure a secure temp location is used)
                ServletContext servletContext = this.getServletConfig().getServletContext();
                File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
                factory.setSizeThreshold(40960);
                factory.setRepository(repository);

                // Create a new file upload handler
                ServletFileUpload upload = new ServletFileUpload(factory);
                upload.setSizeMax(2000000);

                // Parse the request
                try {
                    List<FileItem> items = upload.parseRequest(request);
                }
                catch(Exception ex){
                    ex.printStackTrace();
                }

                // Process the uploaded items
                Iterator<FileItem> iter = items.iterator();

                File uploadedFile = new File(UPLOAD_DIRECTORY,"picture.png");

                // List<FileItem> items is empty - error trying to use the iterator
                FileItem item = iter.next();

                item.write(uploadedFile);
                result = "file upload successful";
            }
            catch (Exception t) {
                t.printStackTrace();
                return result;
            }     
            return result;
        }
        else {
            return "not multipart";
        }
    }

%>

编辑: 所以我认为主要问题是,我没有通过表单中的 action 属性将 jsp 文件与 servlet 连接起来。 我已经创建了上传 servlet 的功能示例,但我需要将 UploadServlet class 导入 JSP 文件而不实际使用 .java 项目文件。 我已经创建了 UploadServlet class 的 jar 文件,并将该 jar 文件添加到 Web 应用程序的 WEB-INF/lib 文件夹中。但是当我尝试创建 UploadServlet class 的实例时,IDE 告诉我它无法解析为类型。

是否可以像这样将用户定义的class导入JSP?我是不是需要更多的依赖?我不确定 tomcat servlet-api.jar 怎么样,UploadServlet jar 可能正在尝试使用它,但 servlet-api classes 在网络应用程序之外.然而,无法将 servlet-api.jar 直接包含在 WEB-INF/lib 网络应用程序下。

UploadServlet.java ---> UploadServlet.jar

package test.pkg;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    public UploadServlet() {
        super();
        // constructor
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // doPost implementation
    }
}
        

JSP 与 UploadServlet

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="test.pkg.UploadServlet" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>File Upload</title>
</head>
<body>
        <form method="post" action="UploadServlet" enctype="multipart/form-data">
            Select file to upload: <input type="file" name="uploadFile" />
            <input type="submit" value="Upload" />
            <%
                UploadServlet servletUp = new UploadServlet();
                servletUp.doPost(request, response);
            %>
        </form>
</body>
</html>

我在回答您之前的评论时,您询问是否可以在 JSP 中定义 Servlet,因为您不确定是否可以访问 Java class在这个项目中。

您可以,因为您可以访问任何 JSP 内的请求和响应,就像任何其他 servlet 一样(JSP 是一个 servlet)。也就是说,您应该将表单与其值的处理分开。一个通常好的模式是 POST-REDIRECT-GET.

我在表单中使用 JSTL,因为这是更好的做法。

为了处理另一个 JSP 中的请求,我不得不求助于 scriptlet,这通常是糟糕设计的标志,但考虑到您无法编辑 Java 源代码,不其他选择...

包含表单的页面:fileUploadForm.jsp

将您的表单设置为 POST 到另一个页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>

<html>
    <head>
        <meta charset="UTF-8">
        <title>My upload file test form</title>
    </head>
    <body>
        <h1>My upload file test form</h1>
        
        <!-- Display messages -->
        <div class="messages">
            <c:if test="${not empty sessionScope.uploadErrors}">
                <c:forEach items="${sessionScope.uploadErrors}" var="err">
                    <p class="error"><c:out value="${err}" /></p>
                </c:forEach>
            </c:if>
            <c:if test="${not empty sessionScope.uploadSuccess}">
                <p class="success">File uploaded successfully: <c:out value="${sessionScope.uploadSuccess}" /></p>
            </c:if>
        </div>
        
        <!-- Form with POST action pointing to uploadFormAction.jsp -->
        <form name="upload-test" action="./uploadFormAction.jsp" method="POST" enctype="multipart/form-data">
            <label for="upload">Upload file:</label>
            <input type="file" name="uploaded" id="upload" accept="image/png" />
            <div class="submits">
                <input type="submit" value="Send" />
            </div>
        </form>
    </body>
</html>

JSP 数据处理代码:fileUploadAction.jsp

处理 POST 请求,记录结果(错误或成功),然后重定向回您的表单以显示它们

<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="java.io.File"%>
<%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    //Storage for error messages
    List<String> errors = new ArrayList<>();
    session.setAttribute("uploadErrors", errors);
    session.setAttribute("uploadSuccess", null);

    //Check for correct form encoding
    if (!"POST".equalsIgnoreCase(request.getMethod())) {
        errors.add("Form must have method=\"POST\"");
    }
    if (!ServletFileUpload.isMultipartContent(request)) {
        errors.add("Form has no multipart data to read from");
    }
    
    if (errors.size() < 1) {
        
        try {
        
            // Create a factory for disk-based file items
            DiskFileItemFactory factory = new DiskFileItemFactory();
    
            // Configure a repository (to ensure a secure temp location is used)
            ServletContext servletContext = this.getServletConfig().getServletContext();
            File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
            factory.setRepository(repository);
    
            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setSizeMax(4L * 1024 * 1024);
    
            // Parse the request
            List<FileItem> items = upload.parseRequest(request);
            String found = null;
            
            for (FileItem item : items) {
                if (item.isFormField()) {
                    //Process other fields in form
                } else if ("uploaded".equals(item.getFieldName())) {
                    if (item.getSize() > 0) {
                        if (found != null) {
                            errors.add("Only one file allowed");
                        } else {
                            found = item.getName();
                            File uploadedFile = new File("./uploads/","picture.png");
                            if (uploadedFile.exists()) uploadedFile.delete();
                            item.write(uploadedFile);
                        }
                    }
                } else { //Other file field
                    //Ignore it ? error ?
                }
            }
            if (found == null) {
                errors.add("No uploaded file !");
            }
            session.setAttribute("uploadSuccess", found);
        } catch (Exception e) {
            e.printStackTrace();
            //Should log it and return it in a more readable form
            errors.add(e.getMessage());
        }
        
    }
        
    response.sendRedirect("uploadFormPage.jsp");

%>

现在考虑你的问题编辑,如果你已经定义了 Servlet class 并想从 JSP 调用它,那么我想你可以使用与在这里描述,并创建一个新的 servlet 实例来调用它的 doPost 方法,在那里你得到 POST 请求,但这是假设你的 servlet 是无状态的并且不使用来自 [=54= 的 init 参数]...

如果你可以写一个Servlet应该怎么做

  1. 保持相同的表单代码,只需将 <form> 的目的地更改为 action="<c:url value ="/uploadFile" />"
  2. 创建您的 Servlet,将 url 模式设置为“/uploadFile”以处理 POST(例如,使用 @WebServlet 注释),并使用与 fileUploadAction.jsp 相同的代码
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@WebServlet("/uploadFile")
public class FileUploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        //Storage for error messages
        List<String> errors = new ArrayList<>();
        session.setAttribute("uploadErrors", errors);
        session.setAttribute("uploadSuccess", null);

        //Check for correct form encoding
        if (!"POST".equalsIgnoreCase(request.getMethod())) {
            errors.add("Form must have method=\"POST\"");
        }
        if (!ServletFileUpload.isMultipartContent(request)) {
            errors.add("Form has no multipart data to read from");
        }
        
        if (errors.size() < 1) {
            
            try {
            
                // Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();
        
                // Configure a repository (to ensure a secure temp location is used)
                ServletContext servletContext = this.getServletConfig().getServletContext();
                File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
                factory.setRepository(repository);
        
                // Create a new file upload handler
                ServletFileUpload upload = new ServletFileUpload(factory);
                upload.setSizeMax(4L * 1024 * 1024);
        
                // Parse the request
                List<FileItem> items = upload.parseRequest(request);
                String found = null;
                
                for (FileItem item : items) {
                    if (item.isFormField()) {
                        //Process other fields in form
                    } else if ("uploaded".equals(item.getFieldName())) {
                        if (item.getSize() > 0) {
                            if (found != null) {
                                errors.add("Only one file allowed");
                            } else {
                                found = item.getName();
                                File uploadedFile = new File("./uploads/","picture.png");
                                if (uploadedFile.exists()) uploadedFile.delete();
                                item.write(uploadedFile);
                            }
                        }
                    } else { //Other file field
                        //Ignore it ? error ?
                    }
                }
                if (found == null) {
                    errors.add("No uploaded file !");
                }
                session.setAttribute("uploadSuccess", found);
            } catch (Exception e) {
                e.printStackTrace();
                //Should log it and return it in a more readable form
                errors.add(e.getMessage());
            }
            
        }
        
        response.sendRedirect("uploadFormPage.jsp");
    }

}