3

I have a Spring Boot application that is an API for a mobile/web app. One of the endpoints accepts a MultipartFile (an image or video) like this:

@RequestMapping(value = "/x/y/z", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> post(@RequestParam("file") MultipartFile file) {
...
}

When the method is called I get the file contents and save it somewhere. However I've noticed a bug - if I kill the network connection on the mobile app during the upload, I don't get any sort of IOException on the API side, and I end up with a truncated byte array:

try {
 InputSteam inputStream = file.getInputStream();
 byte[] allBytes = IOUtils.toByteArray(inputStream);
 inputStream.close();
} catch (Exception ex) {
  //never get to this
}

So the question is: How can I ensure the stream was not interrupted?

Using Spring Boot:

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.3.3.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

Thanks in advance.

Liping Huang
  • 4,378
  • 4
  • 29
  • 46
Manish Patel
  • 4,411
  • 4
  • 25
  • 48
  • probably this should help http://stackoverflow.com/a/25867658/410677 – kuhajeyan Oct 10 '16 at 13:12
  • @kuhajeyan thanks, what are you specifically pointing out here? I already have a MultipartFile reference - presumably it's size would still be truncated? (we are not uploading in chunks) – Manish Patel Oct 10 '16 at 13:16
  • probably, not sure how much it would help you by inspecting the file content/size before it reaches the action. – kuhajeyan Oct 10 '16 at 13:19
  • 1
    the multipart stream is already loaded to the server before you can access this inside your contoller. If the file integrity is significant for you, send it's checksum in conjuction with the multipart itself. – WildDev Oct 10 '16 at 14:53
  • @WildDev thanks. Can you put that as an answer please? – Manish Patel Oct 11 '16 at 07:32

1 Answers1

1

The Multipart stream is already loaded to the server before you can access this inside your controller.

Use checksum to ensure the file is not interrupted.

Calculate it and send along with the Multipart data:

@RequestMapping(...)
public ResponseEntity<?> post(@RequestParam("file") MultipartFile file,
                              @RequestParam("checksum") String checksum) {
    ...
}

After, you can re-calculate the checksum at the server side in order to retrieve the actual checksum to be compared with the received one in bounds of request validation.

WildDev
  • 2,250
  • 5
  • 35
  • 67