Reputation: 2239
Trying to download a pdf doc with Angular, we wrote this:
var _config = { headers : {'Accept' : '*/*'},
responseType : 'arraybuffer'
};
var success = function(data, status, header, config) {
$log.debug('Download resume success - type:' + typeof (data));
var _contentType = (header('Content-Type'));
var blob = new Blob([ data ], { type : _contentType });
var url = (window.URL || window.webkitURL).createObjectURL(blob);
var anchor = angular.element('<a/>');
anchor.attr({
href : url,
target : '_blank',
download : _fileName
})[0].click();
}
$http.get(_url, _config).success(success).error(error);
We've tried all permutations of blob and arraybuffer but data
always returns as a String with the extended characters 'decoded' which is to say broken.
_contentType
is always application/pdf
although we've tried forcing it to application/octet-stream
as well.
Suggestions and pointers welcomed!
Update
This looks to be a bug someplace between Angular (1.3.15 & 1.4.8) and Chrome's (46.0) XMLHttpRequest implementation where response.data is always returned as a 'decoded' string. Neither Firefox (42) nor IE (10) have this problem and all of the solutions below would most likely work (as does or original solution).
I've reported this as a possible bug to both AngularJS & Chrome.
Upvotes: 0
Views: 27903
Reputation: 3520
You need to tell angularjs
that you are receiving a binary file in your $http.get
or $http.post
method. Use {responseType : 'arraybuffer'}
.
For example:
$http.post('/pdf/link', requestData, { responseType : 'arraybuffer' }).then(function (data, status, headers) {
headers = data.headers();
var contentType = headers['content-type'];
var linkElement = document.createElement('a');
try {
var blob = new Blob([data.data], {type: "application/pdf"});
var url = window.URL.createObjectURL(blob);
linkElement.setAttribute('href', url);
linkElement.setAttribute("download", "mypdf.pdf");
var clickEvent = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": false
});
linkElement.dispatchEvent(clickEvent);
} catch (ex) {
console.log(ex);
}
}
Upvotes: 1
Reputation: 555
I ran in to this problem myself a few months back. I had to use FileSaver.js to handle it.
So after you install FileSaver.js have your success function look something like this:
function success(response) {
var blob = new Blob([response.data], { type: "application/pdf"});
//change download.pdf to the name of whatever you want your file to be
saveAs(blob, "download.pdf");
}
Upvotes: 3
Reputation: 10323
Check encoding with your api and in this lines, this worked for me:
var filepdf = Base64.encode(response.data);
$scope.filepdf = 'data:application/pdf;base64,' + pdfdata;
CONTROLLER
$scope.pdfDownloads = function() {
DownloadPath.get({id: $rootScope.user.account_id}, function (data) {
$scope.createtext = "Download PDF file";
$scope.download_pdf_filename = data.filename;
$scope.getPdf = true;
$scope.download_dir = file_url;
$http.get($scope.download_dir).then(function (response) {
var pdfdata= Base64.encode(response.data);
$scope.pdfdata= 'data:application/pdf;base64,' + pdfdata;
$('#pdfanchor').attr({
href: $scope.pdfdata,
download: $scope.download_pdf_filename
})
});
});
};
HTML
<a href=""ng-click="pdfDownloads()" >Download</a>
EDIT: THIS IS HOW WE STRUCTURED THE RESPONSE (PHP functions)
contentType = 'application/octet-stream';
contentDescription = 'File Transfer';
contentDisposition = 'attachment; filename=' . basename(file_nae);
expires = 0;
cacheControl = 'must-revalidate';
contentLength = filesize($file_name);
body = base64_encode(file_get_contents($file_name));
Upvotes: 0
Reputation: 10323
Just change it from your html:
<a target="_self" href="example.com/uploads/file.pdf" download="file_new_name.pdf">
Upvotes: 0