1

I have a controller like so that accepts a MultipartFile and json object:

@PostMapping(value = "/v1/submit")
    public ResponseEntity submit(
              @RequestParam(value="myFile", required = true) MultipartFile myFile
            , @Valid @RequestPart(value="fileMeta", required=true) FileMeta fileMeta
    ){

I need to forward this to a new url using an okhttpclient post with a Multipartbody containing both myFile and fileMeta objects:

OkHttpClient client = new OkHttpClient();
MultipartBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("myFile", myFile.getName(), okhttp3.RequestBody.create(file, MediaType.parse("pdf"))
                .addFormDataPart("fileMeta", fileMeta)
                .build();

I am getting following error: Cannot resolve method 'create(org.springframework.web.multipart.MultipartFile, okhttp3.MediaType)'

OneXer
  • 303
  • 9
  • 20

1 Answers1

1

The method definition of OkHttp's RequestBody create is the following: create(MediaType contentType, byte[] content). It expects the first the MediaType and second the payload (either as byte[], File or other formats).

So you first have to switch the order of the method arguments and second convert the MultipartFile from Spring to a proper format that the create() method accepts, e.g. byte[] or File:

OkHttpClient client = new OkHttpClient();
MultipartBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("myFile", myFile.getName(), RequestBody.create(MediaType.parse("pdf"), file)
                .addFormDataPart("fileMeta", fileMeta)
                .build();

There are already multiple solutions available on StackOverflow to convert MultipartFile to File: How to convert a multipart file to File?

UPDATE: Example for using RestTemplate

@RestController
public class FileSendingController {

  @PostMapping("/files")
  public void streamFile(@RequestParam("file") MultipartFile file) {

    MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
    body.add("file", file);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.postForEntity("http://upload.to", requestEntity, String.class);
  }
}
rieckpil
  • 10,470
  • 3
  • 32
  • 56
  • Thanks @rieckpil, I thought this may be the only way. That surely leads to a large overhead in processing time due to the conversion. Is there no other way to do this? perhaps something okhttp team could look into? – OneXer Mar 09 '20 at 21:17
  • 1
    You could use the Spring `RestTemplate` and use this to make the HTTP call. I am not sure if the OkHttp team wants to invest time to support a file format of a specific framework – rieckpil Mar 10 '20 at 06:04
  • Spring RestTemplate also "makes you" store file locally before it can be posted forward. There must be a technical reason that neither okhttp or Spring RestTemplate cannot just let the file get routed forward or passed through in memory. – OneXer Mar 10 '20 at 11:42
  • I don't think this is true. Most of the example in the internet just give a tutorial on how to do this with a local file. You should be able to do this in-memory – rieckpil Mar 10 '20 at 14:55
  • Do you have any concrete example for in-memory I could use (for example streaming)? – OneXer Mar 10 '20 at 15:21