Search code examples
javajerseymultipartform-data

How do I create a Jersey FormDataContentDisposition object?


I have the following method in a service:

public interface MyService {    
    @POST
    @Path("/upload-file")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    void uploadFile(@FormDataParam("file") InputStream inputStream,
                    @FormDataParam("file") FormDataContentDisposition contentDisposition);
}

and I create an instance of this interface using WebResourceFactory:

final MyService buildProxy() {
    final ClientBuilder clientBuidler = ClientBuilder.newBuilder();
    // register components, trust manager, etc.
    final WebTarget target = clientBuilder.build().target("http://myservice.example.com");
    return WebResourceFactory.newResource(
            MyService.class, target, false, ImmutableMultivaluedMap.empty(), 
            Collections.emptyList(), new Form());
}

I want to call my method using this proxy, but I can't find a convenient way to create a FormDataContentDisposition. Is my best bet really going to be to create the header string, and then pass that into new FormDataContentDisposition(String header)? Can I relax my types somewhere to get access to a more convenient constructor? Is there a different, more convenient interface I can use in a file-upload? I'm mainly including the content-disposition in my interface so I can reject a file that is too large before I save the entire thing to disk.


Solution

  • You can just use FormDataMultipart both on the client side and as the server parameter. FormDataMultiPart gives you access to all the body parts in a programmatic way, instead of declaratively. This will give you a little bit more freedom on the client side. See complete test case below

    public class ProxyMultiPartTest extends JerseyTest {
    
        public static interface IUploadResource {
            @POST
            @Consumes(MediaType.MULTIPART_FORM_DATA)
            String upload(FormDataMultiPart multipart) throws Exception;
        }
    
        @Path("upload")
        public static class UploadResource implements IUploadResource {
            @Override
            public String upload(FormDataMultiPart multiPart) throws Exception {
                FormDataBodyPart bodyPart = multiPart.getField("file");
                FormDataContentDisposition fdcd = bodyPart.getFormDataContentDisposition();
                System.out.println("filename: " + fdcd.getFileName());
                System.out.println("size: " + fdcd.getSize());
                InputStream body = bodyPart.getValueAs(InputStream.class);
                StringWriter writer = new StringWriter();
                ReaderWriter.writeTo(new InputStreamReader(body), writer);
                return writer.toString();
            }
        }
    
        @Override
        public ResourceConfig configure() {
            return new ResourceConfig()
                    .register(UploadResource.class)
                    .register(MultiPartFeature.class)
                    .register(new LoggingFilter(Logger.getAnonymousLogger(), true));
    
        }
    
        @Test
        public void testProxyClientUpload() throws Exception {
            try (Writer writer = new BufferedWriter(new FileWriter("demo.txt"))) {
                writer.write("Hello World");
            }
            WebTarget target = target("upload").register(MultiPartFeature.class);
            IUploadResource resource = WebResourceFactory.newResource(IUploadResource.class, target);
            FileDataBodyPart filePart = new FileDataBodyPart("file", new File("demo.txt"));
            FormDataMultiPart multiPart = new FormDataMultiPart();
            multiPart.bodyPart(filePart);
    
            String response = resource.upload(multiPart);
            assertEquals("Hello World", response);
        }
    }