Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I track file download progress on the back end with Spring Boot?

I have a spring boot app, it has a rest controller that returns strings and text files. I want to track the download progress on the server side, and push messages to a queue.
When working using a HttpServlet I simply got an OutputStream from the HttpResponse object and pushed the bytes over the socket, calculating the progress as they went, like this:

    byte[] buffer = new byte[10];
    int bytesRead = -1;
    double totalBytes = 0d;
    double fileSize = file.length();

    while ((bytesRead = inStream.read(buffer)) != -1) {
        outStream.write(buffer, 0, bytesRead);
        totalBytes += bytesRead;
        queueClient.sendMessage(
                "job: " + job + "; percent complete: " + ((int) (totalBytes / fileSize) * 100));

        }

However, with Spring Boot since a lot of that stuff happens under the hood I'm not 100% sure how to approach it.

I've only just started with Spring Boot so go easy on me! My Controller currently looks like this:

@RestController
@RequestMapping("/api/v1/")
public class MyController {

    @Autowired
    QueueClient queue;

    @RequestMapping(value = "info/{id}", method = RequestMethod.GET)
    public String get(@PathVariable long id) {
        queue.sendMessage("Client requested id: " + id);
        return "You requested ID: " + id;
    }

    @RequestMapping(value = "files/{job}", method = RequestMethod.GET)
    public String getfiles(@PathVariable long job) {
        queue.sendMessage("Client requested files for job: " + job);
        return "You requested files for job " + job;
    }
}

I need to stream files from the server to the client without loading the whole file into memory first. Is this possible with spring REST Controllers?
How can I access the HttpResponse object, or is there another way to do it?

like image 641
mal Avatar asked Oct 30 '22 02:10

mal


1 Answers

HttpResponse object can be fetched and huge file can be downloaded as follows:

@RequestMapping(value = "/files/{job}", method = RequestMethod.GET, produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void downloadFile(@PathVariable("job") String job, HttpServletResponse response) {

//Configure the input stream from the job
    InputStream file = new FileInputStream(fileStoragePath + "\\" + job);

    response.setHeader("Content-Disposition", "attachment; filename=\""+job+"\"");


    int readBytes = 0;
    byte[] toDownload = new byte[100];
    OutputStream downloadStream = response.getOutputStream();

    while((readBytes = file.read(toDownload))!= -1){
        downloadStream.write(toDownload, 0, readBytes);
    }
    downloadStream.flush();
    downloadStream.close(); 
}
like image 96
ArslanAnjum Avatar answered Nov 15 '22 07:11

ArslanAnjum