2014-06-18 10 views
8

Ich kenne eine ähnliche Frage zu diesem: Pdf.js: rendering a pdf file using a base64 file source instead of url. Diese Frage wurde von Codetoffel ehrfürchtig beantwortet, aber meine Frage ist anders, dass mein PDF über einen RESTful-Aufruf meiner Web-API-Implementierung abgerufen wird. Lassen Sie mich erklären ...PDF.JS: Render PDF mit einem ArrayBuffer oder Blob anstelle von URL

Zunächst ist hier eine grundlegende Art und Weise Pdf.js zu verwenden, um ein PDF über eine URL zu öffnen:

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

Dies funktioniert gut, aber ich bin mit Winkel- und seine $resource Service Stellen Sie die Anforderung für das PDF über meine RESTful Web API. Ich weiß, dass PDF.JS es mir erlaubt, die Übergabe der URL als Zeichenfolge in der PDFJS.getDocument-Methode (oben) durch ein DocumentInitParams-Objekt zu ersetzen, das definiert ist. Mit der DocumentInitParams Objekt funktioniert wie folgt:

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

Dies funktioniert auch, aber es funktioniert um mein Eckige $resource von mir erfordert die api URL zu konstruieren. Aber das ist in Ordnung, weil PDFJS mir erlaubt es die PDF-Daten direkt zu geben, anstatt es eine URL in das PDF zu geben, wie folgt:

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

Dies derjenige ist, kann ich nicht scheinen, zu arbeiten. Ich kann die myService.$gtPdf Methode, um die Daten als blob oder als arraybuffer zurückgeben, aber keiner funktioniert. Ich habe versucht, die arraybuffer zurückgegebenen Daten auch zu Uint8Array zu konvertieren, aber ohne Erfolg.

Ich bin mir nicht sicher, was ich noch versuchen könnte und könnte wirklich einen Tipp verwenden.

Wie bekomme ich die von meinem Dienst zurückgegebenen Daten zur Arbeit mit PDFJS?

Vielen Dank im Voraus.

Antwort

17

Sie vorbei nicht die Antwortdaten zu Pdf.js, sondern eine Instanz der Ressource:

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

Sie haben Ihren Code nicht für $getPdf gezeigt, aber ich denke, dass es etwas ist,

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

standardmäßig ein AngularJS $resource behandelt die Antwort als ein Objekt

Äquivalent (deserialisiert von JSON) und kopiert alle Eigenschaften von dem Objekt zu der Ressource-Instanz ( myPdf im vorherigen Snippet).

Offensichtlich wird dies nicht funktionieren, da Ihre Antwort ein Array-Puffer (oder Blob, typisiertes Array oder was auch immer) ist. Eine der Möglichkeiten, die gewünschte Antwort zu bekommen, ist transformResponse zu verwenden, um das Response-Objekt in einem Objekt zu wickeln:

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

Oder einfach die folgenden (vermieden unnötigen lokalen Variablen):

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

Dank! Ich dachte, ich brauche einen PDF.JS-Experten, aber jemand mit besserem Angular-Wissen war wirklich der Schlüssel. Ich habe bereits transformResponse verwendet, aber nicht richtig, da ich die Ressource so behandelte, als wäre es die Antwort. Sobald Sie darauf hingewiesen haben, ist alles andere in Position gekommen. – witttness

+0

Hallo, was machst du mit dem pdf in der.dann um das Dokument in die viewer.html zu laden? – toddmo

+0

Wenn Sie dies mit dem Standard Viewer.html verwenden möchten, verwenden Sie 'PDFViewerApplication.open (myPdf);'. –