Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
504 views
in Technique[技术] by (71.8m points)

javascript - PDF.JS: Render PDF using an ArrayBuffer or Blob instead of URL

I know of a similar question to this one: Pdf.js: rendering a pdf file using a base64 file source instead of url. That question was awesomely answered by Codetoffel but my question is different in that my PDF is retrieved via a RESTful call to my Web API implementation. Let me explain...

First, here's a basic way to use PDF.JS to open a PDF via a URL:

PDFJS.getDocument("/api/path/to/my.pdf").then(function (pdf) {
  pdf.getPage(1).then(function (page) {
    var scale = 1;
    var viewport = page.getViewport(scale);
    var canvas = document.getElementById('the-canvas');
    var context = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    page.render({canvasContext: context, viewport: viewport});
  });
});

This works great, but I am using Angular and its $resource service to make the request for the PDF via my RESTful Web API. I do know that PDF.JS allows me to replace passing the URL as a string in the PDFJS.getDocument method (above) with a DocumentInitParams object, which is defined here. Using the DocumentInitParams object works as follows:

var docInitParams = {
    url: "/api/path/to/my.pdf",
    httpHeaders: getSecurityHeaders(), //as needed
    withCredentials: true
};
PDFJS.getDocument(docInitParams).then(function (pdf) {
    ...
});

This also works, but it works around my Angular $resource by requiring me to construct the api URL. But that's OK because PDFJS allows me to give it the PDF data directly, instead of giving it a URL to the PDF, as follows:

var myPdf = myService.$getPdf({ Id: 123 });

//It's an Angular $resource, so there is a promise to be fulfilled...
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf
    };
    PDFJS.getDocument(docInitParams).then(function (pdf) {
        ...
    });
});

This is the one I can't seem to get to work. I can tell the myService.$gtPdf method to return the data as a blob or as an arraybuffer but neither works. I've tried to convert the arraybuffer returned data to an Uint8Array too, but to no avail.

I'm not sure what else to try and could really use a tip.

How do I get the data returned from my service to work with PDFJS?

Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're not passing the response data to PDF.js, but an instance of the resource:

var myPdf = myService.$getPdf({ Id: 123 });
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf

You haven't shown your code for $getPdf, but I guess that it is something equivalent to

var myService = $resource('/foo', {}, {$getPdf:{responseType: 'arraybuffer'}});
var myPdf = myService.$getPdf();

By default, an AngularJS $resource treats the response as an object (deserialized from JSON) and copies any properties from the object to the resource instance (myPdf in the previous snippet).

Obviously, since your response is an array buffer (or Blob, typed array or whatever), this is not going to work. One of the ways to get the desired response is to use transformResponse to wrap the response object in an object:

var myService = $resource('/foo', {}, {
    $getPdf: {
        responseType: 'arraybuffer',
        transformResponse: function(data, headersGetter) {
            // Stores the ArrayBuffer object in a property called "data"
            return { data : data };
        }
    }
});
var myPdf = myService.$getPdf();
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf.data
    };

    PDFJS.getDocument(docInitParams).then(function (pdf) {
        // ...
    });
});

Or simply the following (avoided unnecessary local variables):

myService.$getPdf().$promise.then(function(myPdf) {
    PDFJS.getDocument({
        data: myPdf.data
    }).then(function (pdf) {
        // ...
    });
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...