2013-12-08 11 views
11

Questo è quello che ho finora:Come si può definire un servizio JAX-RS che elabora dati multiparte in JEE?

Questo inizializza il mio servizio 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 { 
} 

E questo ciò che il mio servizio si presenta come:

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; 
    } 
} 

Ho provato ad aggiungere @MultipartConfig a JaxRsActivator, ma ottengo ancora un'eccezione: Request.getParts è chiamato wi la configurazione multipart. Aggiungi un @MultipartConfig al servlet o un elemento multipart-config a 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$1.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$1.run(ServerRuntime.java:224) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 
    at org.glassfish.jersey.internal.Errors$1.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$9.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.access$100(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) 

Grazie

+0

Assicurati di dare un'occhiata a questa risposta: http://stackoverflow.com/questions/20280626/jax-rs-multipart-response/20354605#20354605 come se usassi GF4 e Jersey 2. –

+0

Grazie, mi sono imbattuto in questo ed è un ottimo collegamento. Sono finalmente riuscito a fare ciò che stavo cercando e cercherò di postare la risposta più tardi oggi. In realtà è possibile farlo usando solo le interfacce. –

risposta

11

Finalmente sono riuscito a far funzionare questo senza l'accoppiamento di Jersey. Il problema è che l'annotazione @Multipart non funziona con lo Application, quindi è necessario definirlo all'interno di web.xml e all'interno della classe Application definire il servizio fornito. All'interno dei servizi è possibile utilizzare normalmente le annotazioni. Si noti inoltre che sto estraendo il Parts dalla richiesta, ma questo è molto semplice.

PS. Questo implementa in realtà il back-end per bluimp JQuery file upload

web.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

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

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); 
    } 

} 
+1

Questo è Java Servlet 3.0 – yegor256

+1

Spiegazione: il '@ MultipartConfig' può essere annotato solo su un'implementazione' Servlet'. Questo è anche esplicitamente dichiarato in javadoc: http://docs.oracle.com/javaee/7/api/javax/servlet/annotation/MultipartConfig.html. – BalusC

4

Credo che ci sia un modo standard per gestire upload di file con JAX-RS. Vedi this question. Il caricamento dei file può essere eseguito in modo specifico per l'implementazione, controllare questo per Jersey.

+0

Euxaristw Niko, come ho detto sopra, sono finalmente riuscito a farlo funzionare usando solo le interfacce. Proverò a postare più tardi. –