如何使用angular.js和java使用大文件逐块下载大文件 [英] how to download large files chunk by chunk using large files using angular.js and java

查看:107
本文介绍了如何使用angular.js和java使用大文件逐块下载大文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个Web应用程序,其中agnular.js中的客户端和java spring中的服务器.我正在研究从客户端下载此日志文件(即logs.tar)的功能.

We have web application with client in agnular.js and server in java spring. I am working on functionality of downloading this log file i.e. logs.tar from client.

当前,我们正在使用Blob进行下载.我们的问题是,如果此日志大小变得很大,例如大于2GB,则在流式传输时会在应用程序内存上造成负载.所以我想要一种方法来逐块下载大文件,而不需要将整个Blob加载到内存中.请建议出路.

Currently we are using blob to download. Our issue is in case this log size becomes huge like greater than 2GB then while streaming it will create load on application memory. so i want way to download large files chunk by chunk and not required to load entire blob into memory. please suggest way out.

服务器端Java代码-

Server side java code -

   public ResponseEntity<?> downloadLogs(HttpServletRequest request) {
        File file = preferencesService.downloadLogs();
        if (file != null) {
            FileInputStream inputStream;
            try {
                inputStream = new FileInputStream(file);
                byte[] content = FileCopyUtils.copyToByteArray(inputStream);

                String filename = "com-logs.tar";
                HttpHeaders responseHeaders = new HttpHeaders();
                responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
                responseHeaders.add(HttpHeaders.CONTENT_TYPE, "application/octet-stream"

);

        return new ResponseEntity<byte[]>(content, responseHeaders, HttpStatus.OK);

        } catch (Exception e) {
            logger.error("Error while processing log file for download", e);
        }
    } else {
        logger.error("Failed to download logs");
    }
    return ResponseEntity.badRequest().build();
} 

客户端Angular.js代码-

Client side Angular.js code -

this._service.downloadLogs().subscribe(
            success => {               
                var blb = new Blob([success], { 'type': "application/octet-stream" });
                if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                    window.navigator.msSaveOrOpenBlob(blb, 'logs.tar');
                }
                else {
                    var link = document.createElement('a');
                    link.href = window.URL.createObjectURL(blb);
                    link.download = "logs.tar";
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                }
            });

新服务器端Java代码-

New Server side java code -

public void downloadLogs(HttpServletResponse resonse) {
        File file = preferencesService.downloadLogs(id);       
        if (file != null) {
            try {
                resonse.setContentType("application/octet-stream");
                resonse.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
                BufferedInputStream inStrem = new BufferedInputStream(new FileInputStream(file));
                BufferedOutputStream outStream = new BufferedOutputStream(resonse.getOutputStream());

                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = inStrem.read(buffer)) != -1) {
                    outStream.write(buffer, 0, bytesRead);
                }
                outStream.flush();
                inStrem.close();

            } 
            ...
        }

推荐答案

重要的是不要将文件读入内存,而是将流传递到:

The important thing is to not read the file into memory, but to pass the stream on:

public ResponseEntity<?> downloadLogs(HttpServletRequest request) {
    File file = preferencesService.downloadLogs();
    if (file != null) {
        try (InputStream inputStream = Files.newInputStream(file.toPath())) {
            InputStreamResource inputStreamResource =
                    new InputStreamResource(new inputStream);
            HttpHeaders responseHeaders = new HttpHeaders();
            //responseHeaders.setContentLength(Files.size(file.toPath()));
            responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="
                    + filename);
            responseHeaders.add(HttpHeaders.CONTENT_TYPE, "application/octet-stream");
            return new ResponseEntity(inputStreamResource, responseHeaders, HttpStatus.OK);
        }
    }
    ...
}

考虑压缩,因为这将大大加快处理速度并减少服务器负载. 应当研究分块,设置内容长度,压缩压缩W​​eb过滤器等.

Consider compression as this will hugely speed things up and cause less server load. Chunking, setting content length, deflate compression web filters, and so on should be looked into.

这篇关于如何使用angular.js和java使用大文件逐块下载大文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆