Add download progress RestTemplate in Java Spring - java

so I am downloading some files using Spring Rest template. I have a requirement to log the progress of the download in backend itself.
So can the download progress be logged in some way ?
Here is my implementation :
File file = restTemplate.execute(FILE_URL, HttpMethod.GET, null, clientHttpResponse -> {
File ret = File.createTempFile("download", "tmp");
StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(ret));
return ret;
});
PS: I was thinking if there is a way to intercept how much of the response body is transferred.

Related

Spring Boot Multipart File Upload - Tips to Improve Performance

I am exposing RESTful API to the reactjs front end application which is used to upload a file to Database.
Server Side Controller Code:
#RequestMapping(value = "/api/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public UploadResponse uploadDocument(#RequestParam("doc") MultipartFile doc,
#RequestParam("metaData") String metaData, HttpServletResponse response) {
// logic to save in DB
return new UploadResponse();
}
Client Side JS Code:
uploadDocument(formData, callback) {
instance.post('/api/upload', formData)
.then((response) => {
callback(response);
})
.catch((error) => {
const errorObj = {
status: error.response.status,
data: {
message: error.response.data.message,
},
};
callback(errorObj);
});
}
application.properties
spring.http.multipart.max-file-size=20MB
spring.http.multipart.max-request-size=20MB
I am trying to upload a 20MB file (CSV or any other) , it is taking too much time to reach the controller side. (~ 1-2 minutes )
Please suggest some good techiniques or tips to improve the performance using same multipart request.
(ex: Chunking or Compressing or Streaming)
I think the easiest way would be to just zip content at javascript side and upload it to you spring boot application.
react js parts: please read upload zip file from reactjs to nodejs
spring boot multipart octet stream handling - necessary classes, test mocks etc. are described at How to go from spring mvc multipartfile into zipinputstream
Using this you should be able to zip content at react side and use it at your spring application.
Or you just zip at react side and upload the file in a normal way without any special octet stream handling in spring boot but just using java zip package classes to unzip files.

Spring Boot serving an m3u8 playlist

I'm trying to serve an m3u8 playlist through Spring Boot. I have a running ffmpeg process that is transcoding a multicast in real-time and sending the files to /src/resources/public/output.m3u8. I see the playlist updating and the new .ts files being generated correctly however when trying to watch the stream in a video player, it only plays a certain amount of video. Is there a way to properly serve up a running playlist in Java instead of serving it statically?
EDIT: When starting a basic http server with python python3 -m http.server, I'm able to view the stream perfectly fine. Is there a Spring Boot way to accomplish the same task?
With Spring 4.1 your approach will work there is no issue in it. Here below is another approach in case if you want to look
#RequestMapping(value = "/VMS-49001/playlist/{listName:.+}")
public ResponseEntity<byte[]> testphoto() throws IOException {
InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/vnd.apple.mpegurl"));
headers.setContentDispositionFormData(fileName, fileName);
return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
}

Stream content from external http resource

I am trying to use my spring boot application as a proxy for certain image or video content hosted externally.
#GetMapping("/video.mp4")
public ResponseEntity<Resource> getVideo(#PathVariable String filename) {
HttpHeaders headers = getHttpHeaders(filename);
ResponseEntity<Resource> exchange = restTemplate.exchange("https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_30mb.mp4", HttpMethod.GET, entity, Resource.class);
return ResponseEntity.ok().headers(headers).body(exchange.getBody());
}
I want to stream the content from the external resource to the client without downloading it first. My sample code above seems to first download the full content in to memory and then serves it.
How can I proxy the content directly without downloading it first?

Java Spark REST api upload file

I'm working with java using java-spark to create the Rest Api and I'm having trouble figuring out how to receive a file so then I can process it. Haven't found anything as like in Spring that handles MultipartFile. Also this proyect is ran on a Tomcat server.
As per the official documentation, the following code you get you started:
post("/yourUploadPath", (request, response) -> {
request.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
try (InputStream is = request.raw().getPart("uploaded_file").getInputStream()) {
// Use the input stream to create a file
}
return "File uploaded";
});

Download a file through Spring MVC controller using streams

I am using spring MVC with REST service for one of my project. I am having a service to attach and download user files.
I am using below service API for upload and save file into server directory
http://myrestserver/attachmentService/attach/userKey
And below service API for download files from server directory
http://myrestserver/attachmentService/download/userKey/fileKey
The issue is that when a file is downloaded, the downloaded URL shows the REST service API URL. To avoid this, I thought of write a controller for attach and download file.
I wrote a spring controller which handle file attachment process. Even I wrote a controller(say download.do) for download a file, but when a file downloaded, the file name shows as the same name of the controller(downloaded file name shows "download.do" always) instead of original file name.
Below code is from my download.do controller
WebResource resource = null;
resource = client.resource("http://myrestserver/attachmentService/download/userKey/fileKey");
clientResponse = resource.accept(MediaType.APPLICATION_OCTET_STREAM).get(
ClientResponse.class);
InputStream inputStream = clientResponse.getEntityInputStream();
if(inputStream != null){
byteArrayOutputStream = new ByteArrayOutputStream();
try {
IOUtil.copyStream(inputStream, byteArrayOutputStream);
} catch (IOException e) {
log.error("Exception in download:"+ e);
}
}
And, in my service API, the code is
file = new File(directory, attachmentFileName);
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(attachmentContent);
fileOutputStream.close();
response = Response.ok((Object) file).type(MediaType.APPLICATION_OCTET_STREAM);
response.header("Content-Disposition", "attachment; filename=" + "\"" + attachmentFileName
+ "\"");
return response.build();
By analyzing the issue, I understood that, am not setting file header in downloaded file through download.do controller.
If I am using outstream in download.do controller, I will not be able to set the file header.
Can any one help me to resolve this issue. My primary aim is to hide my rest service URL from downloaded file by stream through a MVC controller.
I found a post (Downloading a file from spring controllers )in stack overflow almost like my question, but the file type is previously known. Please note that, in my application user can attach any type of file.
You have to set the Content-Disposition prior to writing the file to the output stream. Once you start writing to the output stream, you cannot set headers any longer.

Categories