Java 如何在 JEE 中定义处理多部分数据的 JAX-RS 服务?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20456243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:04:26  来源:igfitidea点击:

How can I define a JAX-RS service that processes multi-part data in JEE?

javaservletsjerseyjax-rsglassfish-4

提问by Ioannis Deligiannis

This is what I have so far:

这是我到目前为止:

This initializes my REST service

这将初始化我的 REST 服务

package com.dothatapp.web.rest;

import javax.servlet.annotation.MultipartConfig;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/authed/rest")
public class JaxRsActivator extends Application {
}

And this what my service looks like:

这就是我的服务的样子:

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;

import org.json.JSONObject;

@Path("fileupload")
public class FileUpload {

    @Context
    private UriInfo context;

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    public JSONObject doUpload(@Context HttpServletRequest obj) {
        try {
            obj.getParts();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        System.out.println(us);
        System.out.println(es);
        System.out.println(obj);
        return null;
    }
}

I tried adding @MultipartConfigto JaxRsActivator, but I still get an Exception: Request.getParts is called without multipart configuration. Either add a @MultipartConfig to the servlet, or a multipart-config element to web.xml.

我尝试添加@MultipartConfigJaxRsActivator,但我仍然得到一个异常:Request.getParts is called without multipart configuration。将 @MultipartConfig 添加到 servlet,或将 multipart-config 元素添加到 web.xml

3-12-08T17:03:05.013+0000|SEVERE: java.lang.IllegalStateException: Request.getParts is called without multipart configuration. Either add a @MultipartConfig to the servlet, or a multipart-config element to web.xml
    at org.apache.catalina.connector.Request.checkMultipartConfiguration(Request.java:4522)
    at org.apache.catalina.connector.Request.getParts(Request.java:4528)
    at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1086)
    at com.dothatapp.web.rest.FileUpload.doUpload(FileUpload.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.invoke(ResourceMethodInvocationHandlerFactory.java:81)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:125)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:91)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:346)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:341)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)
    at org.glassfish.jersey.server.ServerRuntime.run(ServerRuntime.java:224)
    at org.glassfish.jersey.internal.Errors.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:198)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:946)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:323)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at com.dothatapp.web.filter.DoThatAppFilter.doFilter(DoThatAppFilter.java:27)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at com.dothatapp.web.filter.AuthFilter.doFilter(AuthFilter.java:113)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:724)

Thanks

谢谢

采纳答案by Ioannis Deligiannis

Finally I managed to get this working by without Jersey coupling. The problem is that @Multipartannotation doesn't work with the Application, so you need to define it inside web.xml and inside the Applicationclass define the provided service. Inside the services you can use annotations normally. Also note, that I am extracting the Partsfrom the request, but this is very easy.

最后,我设法在没有 Jersey 耦合的情况下完成了这项工作。问题是@Multipart注解不适用于Application,因此您需要在 web.xml 中定义它并在Application类中定义提供的服务。在服务内部,您可以正常使用注释。另请注意,我正在Parts从请求中提取,但这很容易。

PS. This actually implements the back-end for bluimp JQuery file upload

附注。这实际上实现了bluimp JQuery文件上传的后端

web.xml

网页.xml

<servlet>
    <servlet-name>com.web.rest.JaxRsActivator</servlet-name>
    <multipart-config>
        <location>c:\dotmp</location>
        <max-file-size>35000000</max-file-size>
        <max-request-size>218018841</max-request-size>
        <file-size-threshold>0</file-size-threshold>
    </multipart-config>
</servlet>
<servlet-mapping>
    <servlet-name>com.dothatapp.web.rest.JaxRsActivator</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

JaxRsActivator.java

JaxRsActivator.java

    import java.util.HashSet;
    import java.util.Set;

    import javax.ws.rs.core.Application;

    public class JaxRsActivator extends Application {
          @Override
            public Set<Class<?>> getClasses() {
                Set<Class<?>> s = new HashSet<Class<?>>();
                s.add(FileUpload.class);
                return s;
            }
    }

FileUpload.java

文件上传.java

import java.io.IOException;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/")
public class FileUpload {

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Path("fileupload")
    public Response doUpload(@Context HttpServletRequest request) {
        JsonArrayBuilder array = Json.createArrayBuilder();

        try {
            for (Part part : request.getParts()) {
                String name = null;
                long size = 0;
                try {
                    if (part.getContentType() == null
                            || !part.getContentType().toLowerCase()
                                    .startsWith("image/"))
                        continue;

                    name = part.getSubmittedFileName();
                    size = part.getSize();

                    array.add(addFile(name, size, "anId"));
                    part.delete();
                } catch (Exception e) {
                    array.add(addError(name, size, "ERROR"));
                }
            }
        } catch (IOException | ServletException e) {
            e.printStackTrace();
        }

        JsonObject ret = Json.createObjectBuilder().add("files", array).build();
        return Response.status(201).entity(ret).build();
    }

    private JsonObjectBuilder addFile(String name, long size, String url) {
        return Json.createObjectBuilder().add("name", name).add("size", size)
                .add("lid", url);
    }

    private JsonObjectBuilder addError(String name, long size, String error) {
        return Json.createObjectBuilder().add("name", name).add("size", size)
                .add("error", error);
    }

}

回答by Nikos Paraskevopoulos

I believe there is no standard way to handle file uploads with JAX-RS. See this question. File uploading can be done in implementation specific way, check this for Jersey.

我相信没有使用 JAX-RS 处理文件上传的标准方法。看到这个问题。文件上传可以以实现特定的方式完成,请检查Jersey