我需要在客户端使用angular下载文件, 此文件可以是任何格式,可以是pdf或excel或图像或txt ... 我的方法只适用于txt文件,并为我提供了excel和image的失败格式,对于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;
}
你可以看看,告诉我,我错过了什么?
谢谢你:)
答案 0 :(得分:5)
下载二进制文件时,设置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 Reference - XHR ResponseType
答案 1 :(得分:1)
我对后端了解不多,但我会提供我所使用的可能会有所帮助,所以在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(...
在你的后端,确保你的webservice产生八位字节流并以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();
}