0

I've been running into an issue with sending a file as a part of a rest request. Sending the request without the file attached has been fine, but I receive a variety of errors when the file is attached.

I've tested sending the file in postman and have been able to do it successfully. The code that postman generates is:

OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
  .addFormDataPart("id", "123")
  .addFormDataPart("name", "test")
  .addFormDataPart("templateId", "123")
  .addFormDataPart("Files[0].file","/file/path.zip",
    RequestBody.create(MediaType.parse("application/octet-stream"),
    new File("/file/path.zip")))
  .build();
Request request = new Request.Builder()
  .url("url)
  .method("POST", body)
  .addHeader("Authorization", "Bearer token")
  .addHeader("Cookie", "JSESSIONID=sessionid")
  .build();
Response response = client.newCall(request).execute();

Where as I'm using:

        MultiValueMap<String, Object> body
                = new LinkedMultiValueMap<>();

        body.put("id", Collections.singletonList("123"));
        body.put("name", Collections.singletonList("test"));
        body.put("templateId", Collections.singletonList("123"));
        body.put("Files[0].file", Collections.singletonList(new File(filePath)));

        HttpHeaders headers = new HttpHeaders();
        headers.set(AUTHORIZATION, BEARER + token);
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

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

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<ResponseObject> responseObject;

        responseObject= restTemplate.exchange(url, HttpMethod.POST, requestEntity, ResponseObject.class);       

Using the above code has been successful as long as the file isn't attached, however I've tried sending it in a variety of different ways. When I'm making the request the file is being captured from s3 and stored on our eks cluster and I've verified that the file is there. The main difference between the two requests from what I can see is that Postman is setting a media type of application/octet-stream just for the file.

The request appears to want a string, so I've tried sending the file as a byte array and input stream to no avail...although based off the postman code, it seems a File object would be fine.

Edit: The request also works sending it like this:

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addBinaryBody(FILE, new File(filePath));
        builder.addTextBody(FILE_NAME, fileName);
        builder.addTextBody(CUSTOMER_ID, String.valueOf(id));
        builder.addTextBody(name, name);
        builder.addTextBody(TEMPLATE_ID, String.valueOf(templateId));
        

How can I add the file as a binary in the multivalue map?

davo777
  • 286
  • 2
  • 15
  • you can make use of aws sdk instead ? see this, it might help you - https://stackoverflow.com/questions/55204181/upload-zipoutputstream-to-s3-without-saving-zip-file-large-temporary-to-disk-u – Allabakash Dec 17 '20 at 15:19

1 Answers1

0

I needed to be sending the file as a binary in the multivalue map, based on how the other requests were working.

I found this link: RestTemplate send file as bytes from one controller to another

Which mentioned the ByteArrayResource. Having implemented this into my code (below) I can now send the request successfully.

File file = new File(filePath);

        ByteArrayResource resource = new ByteArrayResource(FileUtils.readFileToByteArray(file)) {
            @Override
            public String getFilename() {
                return file.getName();
            }
        };
davo777
  • 286
  • 2
  • 15