Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I have been trying to display pdf file which I am getting as a blob from a $http.post response. The pdf must be displayed within the app using <embed src> for example.

I came across couple of stack posts but some how my example doesnt seem to work.

JS:

according to this doc, I went on and tried...

$http.post('/postUrlHere',{myParams}).success(function (response) {
 var file = new Blob([response], {type: 'application/pdf'});
 var fileURL = URL.createObjectURL(file);
 $scope.content = fileURL;
});

Now from what I understand, fileURL creates a temporary url that the blog can use as refference.

HTML:

<embed src="{{content}}" width="200" height="200"></embed>

I am not sure how to handle this in angular, the ideal situation would be to (1) assign it to a scope, (2) 'prepare/rebuild' the blob to a pdf (3) pass it to the HTML using <embed> cause I want to display it within the app.

I have been researching for more than a day now but some how I cant seem to understand how this works in angular.. and lets just assume the pdf viewer libraries out there weren't an option.

share|improve this question
    
Hi D'lo DeProjuicer, did you manage to get your problem of generating the PDF via angular fixed ? – Raymond Nakampe Sep 4 '14 at 10:20

3 Answers 3

up vote 63 down vote accepted
+50

First of all you need to set the responseType to arraybuffer. This is required if you want to create a blob of your data. See Sending_and_Receiving_Binary_Data. So your code will look like this:

$http.post('/postUrlHere',{myParams}, {responseType:'arraybuffer'})
  .success(function (response) {
       var file = new Blob([response], {type: 'application/pdf'});
       var fileURL = URL.createObjectURL(file);
});

The next part is, you need to use the $sce service to make angular trust your url. This can be done in this way:

$scope.content = $sce.trustAsResourceUrl(fileURL);

Do not forget to inject the $sce service.

If this is all done you can now embed your pdf:

<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>
share|improve this answer
3  
For me this did not work in Chrome (35.0.1916.114 m). Solved this by using <object> instead of <embed>: <object data="{{content}}" type="application/pdf"></object> – HoffZ Jun 16 '14 at 13:34
    
Hi Michael and HoffZ, which js libraries did you include to have your PDF generated as I am experiencing problems about the file(PDF) being corrupt, it's generated but doesn't display in my case. – Raymond Nakampe Sep 4 '14 at 10:18
1  
For me (AngularJS 1.25) I had to do: new Blob([response.data] – Martin Connell Oct 7 '14 at 18:57
1  
@HoffZ: I replaced the shortcut method $http.get with a full one, specifying the responseType field: { url: "http://127.0.0.1:8080/resources/jobs/af471106-2e71-4fe6-946c-cd1809c659e5/resul‌​t/?key="+$scope.key, method: "GET", headers: { 'Accept': 'application/pdf' }, responseType: 'arraybuffer' } And it works :) – Nikolay Melnikov Oct 25 '14 at 23:18
    
Not sure why, since @michael follows the specification. The only difference in my case: I use GET, not post. Source for my solution. – Nikolay Melnikov Oct 25 '14 at 23:25

I use AngularJS v1.3.4

HTML:

<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>

JS controller:

'use strict';
angular.module('xxxxxxxxApp')
    .controller('xxxxController', function ($scope, xxxxServicePDF) {
        $scope.downloadPdf = function () {
            var fileName = "test.pdf";
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.style = "display: none";
            xxxxServicePDF.downloadPdf().then(function (result) {
                var file = new Blob([result.data], {type: 'application/pdf'});
                var fileURL = window.URL.createObjectURL(file);
                a.href = fileURL;
                a.download = fileName;
                a.click();
            });
        };
});

JS services:

angular.module('xxxxxxxxApp')
    .factory('xxxxServicePDF', function ($http) {
        return {
            downloadPdf: function () {
            return $http.get('api/downloadPDF', { responseType: 'arraybuffer' }).then(function (response) {
                return response;
            });
        }
    };
});

Java REST Web Services - Spring MVC:

@RequestMapping(value = "/downloadPDF", method = RequestMethod.GET, produces = "application/pdf")
    public ResponseEntity<byte[]> getPDF() {
        FileInputStream fileStream;
        try {
            fileStream = new FileInputStream(new File("C:\\xxxxx\\xxxxxx\\test.pdf"));
            byte[] contents = IOUtils.toByteArray(fileStream);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/pdf"));
            String filename = "test.pdf";
            headers.setContentDispositionFormData(filename, filename);
            ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
            return response;
        } catch (FileNotFoundException e) {
           System.err.println(e);
        } catch (IOException e) {
            System.err.println(e);
        }
        return null;
    }
share|improve this answer

michael's suggestions works like a charm for me :) If you replace $http.post with $http.get, remember that the .get method accepts 2 parameters instead of 3... this is where is wastet my time... ;)

controller:

$http.get('/getdoc/' + $stateParams.id,     
{responseType:'arraybuffer'})
  .success(function (response) {
     var file = new Blob([(response)], {type: 'application/pdf'});
     var fileURL = URL.createObjectURL(file);
     $scope.content = $sce.trustAsResourceUrl(fileURL);
});

view:

<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>
share|improve this answer
    
Bad mistake. You save my day, thanks. – Kiddo Jul 29 at 4:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.