PDF.JS:使用ArrayBuffer或Blob渲染PDF而不是URL

12

我知道一个类似的问题:Pdf.js:使用base64文件源而不是URL呈现pdf文件。那个问题由Codetoffel令人惊叹地回答了,但我的问题与此不同,在于我的PDF是通过对我的Web API实现进行RESTful调用来检索的。让我解释一下...

首先,这里是使用PDF.JS通过URL打开PDF的基本方法:

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

这种方法很好,但是我正在使用 Angular,并且使用其 $resource 服务通过我的 RESTful Web API 请求 PDF 文件。我知道 PDF.JS 允许我用一个DocumentInitParams 对象替换在上面的 PDFJS.getDocument 方法中传递 URL 字符串,该对象定义在这里。使用 DocumentInitParams 对象的方法如下:

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

这种方法也可以使用,但是它要求我构造API URL以绕过我的Angular$resource。但是这没关系,因为PDFJS允许我直接提供PDF数据而不是提供PDF的URL,如下所示:

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) {
        ...
    });
});

这是我无法使其工作的部分。我可以告诉myService.$gtPdf方法以blobarraybuffer的形式返回数据,但两者都不起作用。我还尝试将返回的arraybuffer转换为Uint8Array, 但没有成功。

我不确定还能尝试什么,真的需要提示。

如何让从服务中返回的数据与PDFJS一起工作?

提前感谢您的帮助。

1个回答

21
您没有将响应数据传递给PDF.js,而是传递了资源的实例:
var myPdf = myService.$getPdf({ Id: 123 });
myPdf.$promise.then(function() {
    var docInitParams = {
        data: myPdf
你没有展示你的$getPdf代码,但我猜它相当于某些内容。
var myService = $resource('/foo', {}, {$getPdf:{responseType: 'arraybuffer'}});
var myPdf = myService.$getPdf();

默认情况下,AngularJS的$resource会将响应视为对象(从JSON反序列化),并将对象的任何属性复制到资源实例(前一个片段中的myPdf)。

显然,由于您的响应是数组缓冲区(或Blob、类型化数组等),因此这样做将不起作用。获得所需响应的方法之一是使用transformResponse将响应对象包装在对象中:

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) {
        // ...
    });
});

或者直接使用以下方法(避免不必要的本地变量):

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

谢谢!我以为我需要PDF.JS专家的意见,但实际上更好的Angular知识才是关键。我已经在使用transformResponse,但是由于将资源视为响应来处理,所以并没有正确使用它。一旦你指出了这一点,其他所有的事情就都顺利解决了。 - witttness
你好,您在.then中如何处理PDF文件以将文档加载到viewer.html中? - toddmo
如果您想在标准的viewer.html中使用它,则使用PDFViewerApplication.open(myPdf); - Rob W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接