Question

I'm trying to get a file with a RESTful API based with JAX-RS on Grails.The file is sent from a regular POST multi-part form with file input tag. ( For sending the file I'm using postman google extention )

But after sending the request I get "HTTP Status 400 - Bad Request" response. I checked many tutorials and followed exactly their steps but it's not working.

Here is the the code in REST service to handle the request :

import com.sun.jersey.multipart.FormDataParam
import com.sun.jersey.core.header.FormDataContentDisposition;
import org.json.simple.JSONObject

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.ws.rs.Consumes
import javax.ws.rs.FormParam
import javax.ws.rs.GET
import javax.ws.rs.POST
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.Context
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@Path('/api/upload/')
class UploadResource {

    @POST
    @Path("/tst")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces('application/json')
    public String uploadFile(@FormDataParam("file") InputStream is, @FormDataParam("file") FormDataContentDisposition fileDetail){

       String uploadedFileLocation = "Some Location";

       // save it
       saveToFile(is, uploadedFileLocation);

        JSONObject JObject = new JSONObject();
        JObject.put("Message", "Aha")
        JObject.put("Response", "200")
        JObject.put("Status", "OK")
        return JObject.toJSONString()
    }
}

And here is the way I send the file :

http://postimg.org/image/x3wfrs6h5/

Was it helpful?

Solution 2

The problem occures because the controller initiated by the jaxrs plugin parses the request upfront and this leads to the error.

This problem is known and there is a workaround for this: https://code.google.com/p/grails-jaxrs/issues/detail?id=52#c11 But it is still a known bug on jaxrs plugin.

OTHER TIPS

Instead of disabling Grails' multipart resolver completely for the whole application (see: https://code.google.com/p/grails-jaxrs/issues/detail?id=52#c11) you could get the file by accessing the multipart file from Grails' WebUtils Holder.

@POST
@Path("/tst")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces('application/json')
public String uploadFile() {

    String uploadedFileLocation = "Some Location";

    // here is the workaround for issue: https://code.google.com/p/grails-jaxrs/issues/detail?id=52
    GrailsWebRequest request = WebUtils.retrieveGrailsWebRequest()
    MultipartFile multipartFile = request.getRequest().getFile('file')
    def is = multipartFile.inputStream

    // save it
    saveToFile(is, uploadedFileLocation);

    JSONObject JObject = new JSONObject();
    JObject.put("Message", "Aha")
    JObject.put("Response", "200")
    JObject.put("Status", "OK")
    return JObject.toJSONString()
}

By default Grails defines a bean named 'multipartResolver' defined for CommonsMultipartResolver, but this does not work with jax-rs as per the reasons detailed by Denny.

The only issue I see with his proposal to use GrailsWebRequest is that if you go to YOUR_APP_URL/application.wadl, you will not see the file param there and therefore auto-generated client code will not work.

What I have done is override this in resources.groovy to:

multipartResolver(org.springframework.web.multipart.support.StandardServletMultipartResolver) { bean ->
   bean.autowire = 'byName'
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top