如何在嵌入式Jetty中实现FileUpload? [英] How to implement FileUpload in embedded Jetty?

查看:123
本文介绍了如何在嵌入式Jetty中实现FileUpload?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个包含Web服务器的android应用。因此,我使用Embedded Jetty(8.0.1)。

I am writing a android app including a webserver. Therefore I use the Embedded Jetty (8.0.1).

下一步,我要做的是实现文件上传。

The next step I want to do is implementing a file upload.

HTML看起来像这样,我认为是正确的:

The HTML looks like that and I think correct:

<form action=\"fileupload\" method=\"post\" enctype=\"multipart/form-data\"> 
    <table>
        <tbody>
            <tr>
                <td><input type=\"file\" name=\"userfile1\" /></td>
            </tr>
            <tr>
                <td>
                     <input type=\"submit\" value=\"Submit\" /><input type=\"reset\" value=\"Reset\" />
                </td>
            </tr>
        </tbody>
    </table>
</form>

当我使用此表单时,我可以在logcat中看到我收到了一个文件,但无法

When I use this form, I can see in logcat that I received a file but I can't access this file in my Servlet.

我尝试过

File file1 = (File) request.getAttribute( "userfile1" );

并具有以下功能:

request.getParameter()

但是每次我收到一个NULL对象时。我该怎么办?

But everytime I receive a NULL Object. What I have to do?

推荐答案

由于这是一个多部分请求,并且您要上传文件部分,因此需要使用

As this is a multipart request, and you are uploading a "file" part, you need to grab the data using

request.getPart("userfile1");

对于请求中非文件类型的元素,例如输入type = text ,那么您可以通过 request.getParameter 访问这些属性。

For elements of your request that are not of type "file", for example input type="text", then you can access those properties through request.getParameter.

请注意,Jetty 8.0.1是很老,最新的Jetty版本(截至撰写本文时为8.1.12)包含一些重要的多部分处理错误修正。

Just to note, Jetty 8.0.1 is quite old, the newest Jetty version (as of writing, 8.1.12) includes some important bugfixes to multipart handling.

如果您升级了Jetty版本,则可能会由于Jetty更严格地执行Servlet 3.0规范( https:/ /bugs.eclipse.org/bugs/show_bug.cgi?id=395000 ),如果使用的是servlet,请使用 @MultipartConfig 批注。

If you upgrade your Jetty version, you will probably have to explicitly enable Multipart handling due to Jetty more strictly enforcing the Servlet 3.0 spec (https://bugs.eclipse.org/bugs/show_bug.cgi?id=395000), use the @MultipartConfig annotation if you are using servlets.

使用处理程序,您必须手动添加 Request .__ MULTIPART_CONFIG_ELEMENT 作为请求的属性,然后再调用 getPart(s)

With handlers you have to manually add a Request.__MULTIPART_CONFIG_ELEMENT as an attribute to your request prior to calling getPart(s)

if (request.getContentType() != null && request.getContentType().startsWith("multipart/form-data")) {
  baseRequest.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);
}

这将允许您解析多部分请求,但会创建临时的多部分文件如果以这种方式注入配置,将不会被清除。对于servlet,它由附加到请求的ServletRequestListener处理(请参阅org.eclipse.jetty.server.Request#MultiPartCleanerListener)。

This will allow you to parse the multipart requests, but the temp multipart files created will not be cleaned if you inject the config in this way. For servlets it is handled by a ServletRequestListener attached to the Request (see org.eclipse.jetty.server.Request#MultiPartCleanerListener).

因此,我们要做的是HandlerWrapper在我们的处理程序链的早期,它在需要时添加多部分配置,并确保在请求完成后清除多部分文件。示例:

So, what we do is have a HandlerWrapper early in our handler chain which adds the multipart config if needed and ensures the multipart files are cleaned after the request has finished. Example:

import java.io.IOException;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiPartInputStreamParser;

/**
 * Handler that adds the multipart config to the request that passes through if
 * it is a multipart request.
 *
 * <p>
 * Jetty will only clean up the temp files generated by
 * {@link MultiPartInputStreamParser} in a servlet event callback when the
 * request is about to die but won't invoke it for a non-servlet (webapp)
 * handled request.
 *
 * <p>
 * MultipartConfigInjectionHandler ensures that the parts are deleted after the
 * {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)}
 * method is called.
 *
 * <p>
 * Ensure that no other handlers sit above this handler which may wish to do
 * something with the multipart parts, as the saved parts will be deleted on the return
 * from
 * {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)}.
 */
public class MultipartConfigInjectionHandler extends HandlerWrapper {
  public static final String MULTIPART_FORMDATA_TYPE = "multipart/form-data";

  private static final MultipartConfigElement MULTI_PART_CONFIG = new MultipartConfigElement(
      System.getProperty("java.io.tmpdir"));

  public static boolean isMultipartRequest(ServletRequest request) {
    return request.getContentType() != null
        && request.getContentType().startsWith(MULTIPART_FORMDATA_TYPE);
  }

  /**
   * If you want to have multipart support in your handler, call this method each time
   * your doHandle method is called (prior to calling getParameter).
   *
   * Servlet 3.0 include support for Multipart data with its
   * {@link HttpServletRequest#getPart(String)} & {@link HttpServletRequest#getParts()}
   * methods, but the spec says that before you can use getPart, you must have specified a
   * {@link MultipartConfigElement} for the Servlet.
   *
   * <p>
   * This is normally done through the use of the MultipartConfig annotation of the
   * servlet in question, however these annotations will not work when specified on
   * Handlers.
   *
   * <p>
   * The workaround for enabling Multipart support in handlers is to define the
   * MultipartConfig attribute for the request which in turn will be read out in the
   * getPart method.
   *
   * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=395000#c0">Jetty Bug
   *      tracker - Jetty annotation scanning problem (servlet workaround) </a>
   * @see <a href="http://dev.eclipse.org/mhonarc/lists/jetty-users/msg03294.html">Jetty
   *      users mailing list post.</a>
   */
  public static void enableMultipartSupport(HttpServletRequest request) {
    request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);
  }

  @Override
  public void handle(String target, Request baseRequest, HttpServletRequest request,
      HttpServletResponse response) throws IOException, ServletException {
    boolean multipartRequest = HttpMethod.POST.is(request.getMethod())
        && isMultipartRequest(request);
    if (multipartRequest) {
      enableMultipartSupport(request);
    }

    try {
      super.handle(target, baseRequest, request, response);
    } finally {
      if (multipartRequest) {
        MultiPartInputStreamParser multipartInputStream = (MultiPartInputStreamParser) request
            .getAttribute(Request.__MULTIPART_INPUT_STREAM);
        if (multipartInputStream != null) {
          try {
            // a multipart request to a servlet will have the parts cleaned up correctly, but
            // the repeated call to deleteParts() here will safely do nothing.
            multipartInputStream.deleteParts();
          } catch (MultiException e) {
//            LOG.error("Error while deleting multipart request parts", e);
          }
        }
      }
    }
  }
}

可以这样使用:

MultipartConfigInjectionHandler multipartConfigInjectionHandler =
    new MultipartConfigInjectionHandler();

HandlerCollection collection = new HandlerCollection();
collection.addHandler(new SomeHandler());
collection.addHandler(new SomeOtherHandler());

multipartConfigInjectionHandler.setHandler(collection);

server.setHandler(multipartConfigInjectionHandler);

这篇关于如何在嵌入式Jetty中实现FileUpload?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆