0

Related to Need to open blob/PDF in IE window and Setting window.location or window.open in AngularJS gives "access is denied" in IE 11.

I need to open a PDF which comes from a byte array in my service:

@RequestMapping("/{dokumentId}")
public ResponseEntity<byte[]> getDoc(@PathVariable Integer docId, HttpServletRequest request, HttpServletResponse response) throws IOException {       
    byte[] contents = // .. get document 

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.parseMediaType("application/pdf"));
    headers.add("Content-Disposition", "inline;filename=file");
    headers.add("Cache-Control","private, must-revalidate, post-check=0, pre-check=0, max-age=1");
    headers.add("Pragma", "no-cache");
    headers.setContentLength(contents.length);

    return new ResponseEntity<>(contents, headers, HttpStatus.OK);
}

which I'm trying to open in Internet Explorer 11 with the following JS:

$scope.openPdf = function(doc){
    var winlogicalname = "document_" + doc.docId;
    var winparams = 'dependent=yes,locationbar=no,scrollbars=yes,menubar=yes,resizable,screenX=50,screenY=50,width=850,height=1050';

    var ieEDGE = navigator.userAgent.match(/Edge/g);
    var ie = navigator.userAgent.match(/.NET/g); // IE 11+
    var oldIE = navigator.userAgent.match(/MSIE/g); 

    if(!ie && !oldIE && !ieEDGE){
        // Open PDF in new browser window
        var detailWindow = window.open("", winlogicalname, winparams);
    }

    xxxService.getDoc(doc).success(function(data){
        //for browser compatibility  
        if (ie || oldIE || ieEDGE) {
            var blob = new window.Blob([data], { type: 'application/pdf' });    
            window.navigator.msSaveOrOpenBlob(blob);
        } else {
            var binaryAsString = ArrayBufferToString(data).replace(/"/g,"");
            var pdfAsDataUri = "data:application/pdf;base64," + binaryAsString;
            var htmlText = '<embed width=100% height=100% type="application/pdf" src="'+ pdfAsDataUri + '"></embed>'; 
            detailWindow.document.write(htmlText);
            detailWindow.document.close();
        }   
    }).error(function(data, status, headers, config){
        console.log(data, status, headers, config);
    });
};

This works in Chrome and Firefox (opens in new window, constructed directly from binary with <embed>. However, this way does not seem to work in IE, hence msSaveOrOpenBlob. But when saving/opening the PDF in IE, I get an error in Adobe Reader: "Adobe Acrobat Reader DC could not open 'file.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).". When I try to drag and drop the PDF in to IE, it says "File does not begin with '%PDF-'.".

Any ideas on how to open a PDF in IE11 using either byte array directly or constructing a Blob?

Community
  • 1
  • 1
Jesper N
  • 2,115
  • 4
  • 23
  • 32

1 Answers1

1

I changed my web service to this:

byte[] contents = // get contents

response.getOutputStream().write(contents);
response.setContentType("application/pdf");
response.setContentLength(contents.length);
response.addHeader("Content-Disposition", "inline;filename="+filename);
response.addHeader("Cache-Control", "private, must-revalidate, post-check=0, pre-check=0, max-age=1");
response.addHeader("Pragma", "public");

and then consumed on client side with:

Service.getDocument(docId).success(function(data){
    var file = new Blob([data], {type: 'application/pdf'});
    if(window.navigator.msSaveOrOpenBlob){
        window.navigator.msSaveOrOpenBlob(file, name + ".pdf");
    } else {
        var fileURL = URL.createObjectURL(file);
        $scope.renderPDF(fileURL, detailWindow.document.getElementById('canvas'));
    } 
}

where $scope.renderPDF uses PDFJS to render the PDF in a new window. Remember to set {responseType:'arraybuffer'}) on the $http.get (or post) method.

Jesper N
  • 2,115
  • 4
  • 23
  • 32