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