Search code examples
springrestgrailsjerseymultipartform-data

Grails JAX-RS REST multipart file upload


Trying to get a multipart file upload to work in a Grails 2.5.4 resource.

I'd really like to use Spring's out of the box multipart features, but I cannot find an example for my particular case.

I am calling the API from Postman. Body with form-data and a single PDF file attached in a file field. No other headers!

First try

@POST
@Path("/pdf")
Response createPdf(MultipartFile file)

Gives back 415 Unsuported Media Type in Postman, and this on the server:

[...] ERROR container.ContainerRequest  - A message body reader for Java class org.springframework.web.multipart.MultipartHttpServletRequest [...]
The registered message body readers compatible with the MIME media type are:
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
  com.sun.jersey.core.impl.provider.entity.EntityHolderReader
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General

Adding @Consumes(MediaType.MULTIPART_FORM_DATA) does not help.

I've tried other params such as MultipartHttpServletRequest but there's still no message body reader.

Second try

@POST
@Path("/pdf")
@Consumes(MediaType.MULTIPART_FORM_DATA)
Response createPdf(@FormDataParam("file") InputStream uploadedInputStream,
                       @FormDataParam("file") FormDataContentDisposition fileDetail) 

Gives back a 500 error, and this on the server:

SEVERE: Missing dependency for method public javax.ws.rs.core.Response com.carfax.VehicleReceiptPhotoResource.createPdf(java.io.InputStream,org.glassfish.jersey.media.multipart.FormDataContentDisposition) at parameter at index 0
SEVERE: Missing dependency for method public javax.ws.rs.core.Response createPdf(java.io.InputStream,org.glassfish.jersey.media.multipart.FormDataContentDisposition) at parameter at index 1
SEVERE: Method, public javax.ws.rs.core.Response createPdf(java.io.InputStream,org.glassfish.jersey.media.multipart.FormDataContentDisposition), annotated with POST of resource, class com.carfax.VehicleReceiptPhotoResource, is not recognized as valid resource method.

having these dependencies

compile group: 'com.sun.jersey', name: 'jersey-bundle', version: '1.19.4'
compile group: 'com.sun.jersey', name: 'jersey-json', version: '1.19.4'

compile "javax.ws.rs:javax.ws.rs-api:2.1@jar"
compile ('org.glassfish.jersey.media:jersey-media-multipart:2.27') {
    exclude group:'javax.ws.rs'
}
compile group: 'org.jvnet.mimepull', name: 'mimepull', version: '1.9.11'

Third try

@POST
@Path("/pdf")
Response createPdf(@FormDataParam("file") InputStream fileInputStream)

With the same jersey dependencies as in the second attempt, this works, but it's not good enough for me. I'd like to upload multiple files at once, and get some extra json info on the side.

What I want

  • Some clarification on how many methods of multi file upload are there in Grails
  • What are the different libraries achieving this
  • To do this in a Grails REST resource, not in a controller

Some links I went through


Solution

  • *as per Paul Samsotha's comment

    You're trying to mix Jersey 2.x multipart support with a Jersey 1.x application. This isn't going to work. You need to use the 1.x multipart. Get rid of the 2.x one.