二进制文件损坏 – 如何使用AngularJS下载二进制文件

使用ResponseEntity以angular度下载任何文件不起作用

我需要在客户端使用angular度下载文件,这个文件可以有任何格式,它可能是一个PDF或Excel或图像或​​TXT …我的方法只适用于TXT文件,并给我一个失败格式的Excel和图像和为PDF提供了一个空的PDF。

所以在我的控制器中这里是调用服务方法的函数:

vm.downloadFile = downloadFile; function downloadFile(file){ var urlDir = "C://STCI//"+idpeticion; return VerDocServices.downloadFile(file,urlDir) .then(function(response) { var data = response.data; var filename = file; var contentType = 'application/octet-stream';//octet-stream var linkElement = document.createElement('a'); try { var blob = new Blob([ data ], { type : contentType }); var url = window.URL.createObjectURL(blob); linkElement.setAttribute('href', url); linkElement.setAttribute("download", filename); var clickEvent = new MouseEvent("click", { "view" : window, "bubbles" : true, "cancelable" : false }); linkElement.dispatchEvent(clickEvent); } catch (ex) { console.log(ex); throw ex; } }).catch(function(response) { alert('Se ha producido un error al exportar del documento'); console.log(response.status); throw response; }); } 

和我的service.js有:

 angular.module('mecenzApp').service('VerDocServices',['$http',function($http) { this.downloadFile = function(file,urlDir) { return $http.get('api/downloadFile', { params : { file : file, urlDir : urlDir } }); }} ]); 

而我的服务方式是这样的:

 @GetMapping("/downloadFile") @Timed public ResponseEntity<byte[]> downloadFile(@RequestParam(value = "file") String file, @RequestParam(value = "urlDir") String urlDir) { log.debug("GET ---------------- DOWNLOAD FILE : {}", file); log.debug("GET ---------------- From the DIRECTORY: {}",urlDir); InputStream fileStream; String filepath = urlDir+File.separator+file; try { File f = new File(filepath); log.debug("GET ---------------- FILE: {}",f.getPath()); fileStream = new FileInputStream(f); byte[] contents = IOUtils.toByteArray(fileStream); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/octet-stream")); String filename = file; headers.setContentDispositionFormData(filename, filename); ResponseEntity<byte[]> response2 = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK); fileStream.close(); return response2; } catch (FileNotFoundException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); } return null; } 

你可以看看,告诉我我错过了什么?

谢谢youuu 🙂

如何使用AngularJS下载二进制文件

下载二进制文件时,重要的是设置responseType

 app.service('VerDocServices',['$http',function($http) { this.downloadFile = function(url, file, urlDir) { var config = { //SET responseType responseType: 'blob', params : { file : file, urlDir : urlDir } }; return $http.get(url, config) .then(function(response) { return response.data; }).catch(function(response) { console.log("ERROR: ", response.status); throw response; }); }; }]); 

如果省略responseType则XHR API将默认将UTF-8编码的文本转换为DOMString(UTF-16) ,这会破坏PDF,图像和其他二进制文件。

有关更多信息,请参阅MDN Web API参考 – XHR ResponseType

我不太了解后端,但我会提供我所使用的可能会有所帮助,所以在Java脚本文件:

 //your $http(request...) .success(function (data, status, headers, config) { //Recieves base64 String data var fileName = 'My Awesome File Name'+'.'+'pdf'; //Parsing base64 String... var binaryString = window.atob(data); var binaryLen = binaryString.length; var fileContent = new Uint8Array(binaryLen); for (var i = 0; i < binaryLen; i++) { var ascii = binaryString.charCodeAt(i); fileContent[i] = ascii; } var blob = new Blob([fileContent], { type: 'application/octet-stream' }); //octet-stream var fileURL = window.URL.createObjectURL(blob); $sce.trustAsResourceUrl(fileURL); //allow angular to trust this url //Creating the anchor download link var anchor = angular.element('<a/>'); anchor.css({display: 'none'}); // Make sure it's not visible angular.element(document.body).append(anchor); // Attach it to the document anchor.attr({ href: fileURL, target: '_blank', download: fileName })[0].click(); anchor.remove(); // Clean it up afterwards }) //.error(function(... 

并在您的后端,请确保您的web服务产生octet-stream并以base64数据格式返回文件,我这样做使用Java JAX-RS是这样的:

 @POST @Path("/downloadfile") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response downloadFile(...){ String base64String = Base64.getEncoder().encodeToString(/*here you pass your file in byte[] format*/); return Response.ok(base64String).build(); }