Reputation:
[context: java 8, spring boot 1.5.1]
We are creating a RESTful service where we need to be able to upload large files. What I want is an api that would look something like this
@RequestLine("POST /object")
@Headers("Content-Type: multipart/form-data")
void create(InputStreamResource resource, ...);
I don't want to use a MultipartFile
as the entire file would be read, nor an HttpServletRequest
as that doesn't seem to belong here but rather begs the need for a HttpMessageConverter
of sorts. Having said that, with an HttpServletRequest
I could solve the problem as follows
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
FileItemStream e = iterator.next();
if (!e.isFormField()) {
InputStream inputStream = item.openStream();
//...
}
}
Ideally I would like an InputStream
or something that wraps one, e.g. InputStreamResource
(as shown above).
Any suggestions would be appreciated.
Upvotes: 4
Views: 11885
Reputation: 987
I got it working in this way and it seems the only way to handle upload without temp file or reading the file into byte array using @RequestBody annotation, as was suggested on stackoverflow.com in one thread:
@RequestMapping("firmware/{firmwareId:\\d+}/logs/upload")
public
@ResponseBody
ResponseEntity handleUploadLogs(@PathVariable("firmwareId") final Long firmwareId, final HttpServletRequest request) {
try (final InputStream is = getInputStream(request)) {
if (is != null) {
firmwareContentService.uploadLogs(firmwareId, is);
return ok().build();
} else {
return badRequest().build();
}
} catch (IOException | FileUploadException e) {
return badRequest().build();
}
}
private InputStream getInputStream(final HttpServletRequest request) throws IOException, FileUploadException {
final ServletFileUpload upload = new ServletFileUpload();
final FileItemIterator iterator = upload.getItemIterator(request);
InputStream is = null;
while (iterator.hasNext()) {
final FileItemStream item = iterator.next();
if (!item.isFormField()) {
is = item.openStream();
break;
}
}
return is;
}
UPDATE
This simple code worked for me as well. Just put InputStream into method parameters:
@PostMapping("firmware/{firmwareId:\\d+}/logs/upload")
public
@ResponseBody
ResponseEntity handleUploadLogs(@PathVariable("firmwareId") final Long firmwareId, final InputStream is) {
try {
firmwareContentService.uploadLogs(firmwareId, is);
return ok().build();
} catch (IOException e) {
return badRequest().build();
}
}
The "simple code" above is not actually working. InputStream in method parameter contains whole http request.
Upvotes: 1