【问题标题】:Simple Jetty/JSF file upload won't submit简单的 Jetty/JSF 文件上传不会提交
【发布时间】:2020-03-31 12:29:26
【问题描述】:

I've already looked at this one 和相关的票都没有用。

我有,看起来可能是最简单的例子

<h:form enctype="multipart/form-data"  prependId="false">
<h:outputText value="File: "></h:outputText>
<h:inputFile value="#{configUploadController.uploadedFile}"  />
<h:commandButton value="Save" type="submit" action="#{configUploadController.uploadFile}" style="color: red;"></h:commandButton>
</h:form>

我在我的uploadFile 方法中设置了一个断点,但它从来没有被击中。当我从它尝试提交的表单中删除 enctype 时,我得到了明显的错误......

javax.servlet.ServletException: Content-Type != multipart/form-data

为了完整起见,我删除了&lt;h:inputFile&gt;enctype,可以看到我的断点被命中。当我将 enctype 设置为 text/plain 时,它 DOESNT 到达断点。但是,当我将 enctype 设置为乱码时,它 确实 会遇到断点 :(

我是否在某处缺少依赖项或配置?

如果重要的话,我的 web.xml...

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

    <!-- File(s) appended to a request for a URL that is not mapped to a web 
        component -->
    <welcome-file-list>
        <welcome-file>status.xhtml</welcome-file>
    </welcome-file-list>

    <context-param>
        <param-name>com.sun.faces.expressionFactory</param-name>
        <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
    </context-param>

    <listener>
        <description>Initializes Oracle JSF</description>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
    </listener>

    <!-- Define the JSF servlet (manages the request processing life cycle for 
        JavaServer Faces) -->
    <servlet>
        <servlet-name>faces-servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>

    <!-- Map following files to the JSF servlet -->
    <servlet-mapping>
        <servlet-name>faces-servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>


</web-app>
  • jsf-api-2.2.15
  • jsf-impl-2.2.15
  • el-api-2.2
  • el-impl-2.2
  • 码头 9.4.18
  • javax.servlet-api-3.1.0

【问题讨论】:

标签: jsf jetty


【解决方案1】:

实际问题是 Jetty 需要为每个多部分请求设置多部分配置,而不是使用 servlet(根据其他答案)。

执行此操作的简单方法是添加一个过滤器,根据需要添加它,例如。

public class LoginFilter implements Filter {

  private static final String MULTIPART_FORM_DATA = "multipart/form-data";
  private static final MultipartConfigElement MULTI_PART_CONFIG =
        new MultipartConfigElement(System.getProperty("java.io.tmpdir"));

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;

    String contentType = request.getContentType();
    if (contentType != null && contentType.startsWith(MULTIPART_FORM_DATA))
        request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);

    filterChain.doFilter(request, response);
  }
}

另请参阅:

【讨论】:

    【解决方案2】:

    所以,我没有花时间追查原因,但码头似乎不喜欢多部分表单。我通过使用 servlet 解决了这个问题。解决方案看起来像这样......

    我使用了 ajax 方法和 HTML 表单,因此我可以指定与 servlets 模式匹配的操作...

    <form action="upload/config" enctype="multipart/form-data" method="post">
        <h:inputFile id="file" />
        <br />
        <h:commandButton type="submit" value="Upload">
            <f:ajax execute="file" render="@all"/>
        </h:commandButton>
    </form>
    

    还有 servlet...

    import java.io.InputStream;
    import java.io.OutputStream;
    import java.nio.file.Files;
    import java.nio.file.Path;
    
    import javax.servlet.MultipartConfigElement;
    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;
    
    import org.eclipse.jetty.server.Request;
    
    @WebServlet("upload")
    @MultipartConfig
    public class UploadServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse resp) {
    
            try {
                // This needed to get access to the parts
                MultipartConfigElement multipartConfigElement = new MultipartConfigElement((String)null);
                request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, multipartConfigElement);
    
                Part filePart = request.getPart("file");
    
                try ( InputStream inputStream = filePart.getInputStream(); ) {
                    // Do what you want with your part
    
                } catch (Exception e) {
                    resp.setStatus(500);
                }
    
    
            } catch (Exception e) {
                resp.setStatus(500);
            }
        }
    }
    

    【讨论】:

    • 不是 Jetty 不喜欢多部分表单,而是 HTTP 客户端没有提交带有请求标头 Content-Type: multipart/form-data 的 POST,异常告诉您它为 Content-Type 获得了其他值(不支持)
    • 我继续更新该异常消息以更清晰 - eclipse/jetty.project@53eda032
    • @JoakimErdfelt:我不认为 OP 说 Jetty 不喜欢多部分表单。 OP 表示,使用此enctype="multipart/form-data" 不会调用该方法,如果没有它,则会发生上述错误。这是有道理的,因为 `multipart/form-data' 是预期的并且没有发送(因为它没有设置)。
    猜你喜欢
    • 2013-07-23
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多