Arquivos binários corrompidos – Como baixar arquivos binários com o AngularJS

baixar qualquer arquivo usando ResponseEntity com angular não funciona

Eu preciso baixar um arquivo usando angular no lado do cliente, este arquivo pode ter qualquer formato que poderia ser um pdf ou excel ou imagem ou txt … meu método funciona apenas para arquivos txt e me dá um formato de falha para excel e imagem e para o pdf dá um pdf vazio.

então no meu controlador aqui está a function que chama o método de serviço:

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; }); } 

e meu service.js tem:

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

E meu método de serviço é este:

 @GetMapping("/downloadFile") @Timed public ResponseEntity 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 response2 = new ResponseEntity(contents, headers, HttpStatus.OK); fileStream.close(); return response2; } catch (FileNotFoundException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); } return null; } 

você poderia plz dar uma olhada e me diga o que eu perdi?

Obrigado youuu 🙂

Como baixar arquivos binários com o AngularJS

Ao baixar arquivos binários, é importante definir o 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; }); }; }]); 

Se o responseType for omitido, os padrões da API do XHR serão convertidos em texto codificado em UTF-8 para DOMString (UTF-16), o que corromperá arquivos PDF, imagens e outros arquivos binários.

Para obter mais informações, consulte Referência da API da Web do MDN – XHR ResponseType

Eu não sei muito sobre o backend, mas vou fornecer o que eu usei pode ser que vai ajudar, então no arquivo de script 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(''); 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(... 

E no seu backend, certifique-se de que seu webservice produzia o octet-stream e retornando o arquivo no formato de dados base64, eu fiz isso usando o Java JAX-RS assim:

 @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(); }