【问题标题】:PDF Blob - Pop up window not showing contentPDF Blob - 弹出窗口不显示内容
【发布时间】:2014-03-10 20:50:08
【问题描述】:

过去几天我一直在研究this problem。尝试在<embed src> 标签上显示流没有运气,我只是尝试在新窗口上显示它。

新窗口显示 PDF 仅控件 )

知道为什么 pdf 的内容没有显示吗?

代码:

$http.post('/fetchBlobURL',{myParams}).success(function (data) {
    var file = new Blob([data], {type: 'application/pdf'});
    var fileURL = URL.createObjectURL(file);
    window.open(fileURL);
});

【问题讨论】:

标签: javascript angularjs pdf


【解决方案1】:

如果您想根据响应数据创建blob,则需要将responseType 设置为arraybuffer

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

更多信息:Sending_and_Receiving_Binary_Data

【讨论】:

  • 对我不起作用。在浏览器窗口中键入 URL 时,它可以工作,但不是通过 $http.post 方法。还有什么需要注意的吗?安全设定?浏览器类型和版本?
  • 它正在工作。似乎 arrayBuffer 是在 angularjs 中从 v.1.1 开始实现的。我有 v.1.08。升级 angularjs 时,一切正常。
  • 这几乎对我有用。我需要这样做,但我必须设置一个用户友好的 URL 或文件名。浏览器设置的 UUID 对我不起作用。您知道是否有办法在新选项卡中打开 PDF 并在 URL 中设置文件名?谢谢!
  • 你能帮忙解决这个stackoverflow.com/questions/63187758/…吗?
  • URL.createObjectURL() 已从 Chrome 71 中弃用。developers.google.com/web/updates/2018/10/chrome-71-deps-rems 你不能再使用它了。
【解决方案2】:

我使用 AngularJS v1.3.4

HTML:

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

JS 控制器:

'use strict';
angular.module('xxxxxxxxApp')
    .controller('MathController', function ($scope, MathServicePDF) {
        $scope.downloadPdf = function () {
            var fileName = "test.pdf";
            var a = document.createElement("a");
            document.body.appendChild(a);
            MathServicePDF.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 服务:

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

Java REST Web 服务 - 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;
    }

【讨论】:

    【解决方案3】:

    如果您设置了{ responseType: 'blob' },则无需自行创建Blob。您可以简单地根据响应内容创建 url:

    $http({
        url: "...",
        method: "POST",
        responseType: "blob"
    }).then(function(response) {
        var fileURL = URL.createObjectURL(response.data);
        window.open(fileURL);
    });
    

    【讨论】:

    • 太棒了!在花了很多时间尝试显示 pdf 内容之后,这对我有用。
    • ncaught TypeError:无法在“URL”上执行“createObjectURL”:未找到与提供的签名匹配的函数。在 Object.success (enquiry.js:68) 在 j (jquery.js:2) 在 Object.fireWith [as resolveWith] (jquery.js:2) 在 x (jquery.js:4) 在 XMLHttpRequest. (jquery.js:4)
    • @ThakhaniTharage 您使用哪种浏览器?检查compatibility table
    • 你能帮忙解决这个stackoverflow.com/questions/63187758/… 吗?
    【解决方案4】:

    我苦苦挣扎了好几天终于找到了适合我的解决方案。我必须让window.print() for PDF in new window 需要工作。

     var xhr = new XMLHttpRequest();
          xhr.open('GET', pdfUrl, true);
          xhr.responseType = 'blob';
    
          xhr.onload = function(e) {
            if (this['status'] == 200) {          
              var blob = new Blob([this['response']], {type: 'application/pdf'});
              var url = URL.createObjectURL(blob);
              var printWindow = window.open(url, '', 'width=800,height=500');
              printWindow.print()
            }
          };
    
          xhr.send();
    

    关于在新窗口中加载 PDF 和打印的一些注意事项。

    • 可以通过 iframe 在新窗口中加载 pdf,但如果 url 是外部 url,则打印将不起作用。
    • 必须允许浏览器弹出窗口,然后才会起作用。
    • 如果您尝试从外部 url 加载 iframe 并尝试window.print(),您将得到空打印或不包括iframe 的元素。但是您可以手动触发打印,这将起作用。

    【讨论】:

    • 这对我不起作用我得到了 enquiry.js:85 Uncaught TypeError: Cannot read property 'print' of null at XMLHttpRequest.xhr.onload
    • 新窗口打开了吗?这个示例之前为我工作过。
    • 不,它没有
    • pdf URL 必须来自同一服务器。否则会显示 CORS 错误。
    • 查看工作示例链接pdf-print-pckrishnadas88.c9users.io/hello-world.html。请注意,它是一个免费帐户,可以使用几个小时。
    【解决方案5】:

    我最终只是使用下面的代码下载了我的 pdf

    function downloadPdfDocument(fileName){
    
    var req = new XMLHttpRequest();
    req.open("POST", "/pdf/" + fileName, true);
    req.responseType = "blob";
    fileName += "_" + new Date() + ".pdf";
    
    req.onload = function (event) {
    
        var blob = req.response;
    
        //for IE
        if (window.navigator && window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveOrOpenBlob(blob, fileName);
        } else {
    
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = fileName;
            link.click();
        }
    };
    
    req.send();
    

    }

    【讨论】:

    • 开始下载。
    • 这就是我想要的,这就是为什么它在一个函数中,以便我可以在准备下载时调用它。不知道你为什么投反对票
    【解决方案6】:

    问题是,它没有转换为正确的格式。使用函数"printPreview(binaryPDFData)"获取二进制pdf数据的打印预览对话框。 如果您不想打开打印对话框,可以评论脚本部分。

    printPreview = (data, type = 'application/pdf') => {
        let blob = null;
        blob = this.b64toBlob(data, type);
        const blobURL = URL.createObjectURL(blob);
        const theWindow = window.open(blobURL);
        const theDoc = theWindow.document;
        const theScript = document.createElement('script');
        function injectThis() {
            window.print();
        }
        theScript.innerHTML = `window.onload = ${injectThis.toString()};`;
        theDoc.body.appendChild(theScript);
    };
    
    b64toBlob = (content, contentType) => {
        contentType = contentType || '';
        const sliceSize = 512;
         // method which converts base64 to binary
        const byteCharacters = window.atob(content); 
    
        const byteArrays = [];
        for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            const slice = byteCharacters.slice(offset, offset + sliceSize);
            const byteNumbers = new Array(slice.length);
            for (let i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }
            const byteArray = new Uint8Array(byteNumbers);
            byteArrays.push(byteArray);
        }
        const blob = new Blob(byteArrays, {
            type: contentType
        }); // statement which creates the blob
        return blob;
    };
    

    【讨论】:

      【解决方案7】:
      // I used this code with the fpdf library.
      // Este código lo usé con la libreria fpdf.
      
      var datas = json1;
      var xhr = new XMLHttpRequest();
      xhr.open("POST", "carpeta/archivo.php");
      xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
      xhr.responseType = "blob";
      xhr.onload = function () {
          if (this.status === 200) {
              var blob = new Blob([xhr.response], {type: 'application/pdf'});
              const url = window.URL.createObjectURL(blob);
              window.open(url,"_blank");
              setTimeout(function () {
                  // For Firefox it is necessary to delay revoking the ObjectURL
                  window.URL.revokeObjectURL(datas)
                      , 100
              })
          }
      };
      xhr.send("men="+datas);
      

      【讨论】:

        【解决方案8】:

        我知道这已经过时了,但既然这为我指明了正确的方向,我想我会分享我正在做的事情,以防其他人登陆这里。顺便说一句,我没有使用 Angular。

        用户可以查看或下载文件。选择是通过 2 个按钮或 2 个链接给出的

        <button type="button" class="btn btn-primary btn-sm show_tooltip download-form" title="Download File" data-formid="{{ @your-id }}" data-forcedownload="1">
            <i class="fas fa-file-download"></i>
        </button>
        
        <button type="button" class="btn btn-primary btn-sm show_tooltip download-form" title="View File" data-formid="{{ @your-id }}" data-forcedownload="0">
            <i class="fas fa-search"></i>
        </button>
        

        我将 jQuery 与 xhr2 的本机插件一起使用。这处理链接/按钮

        $('.download-form').click(function(event) {
            event.preventDefault();
            let fid = $(this).data('formid');
            let force_download = $(this).data('forcedownload');
            $.ajax({
                  url: '/download',
                  dataType: 'native',
                  type: 'POST',
                  xhrFields: {
                      responseType: 'blob'
                  },
                  data: {
                       //you can send any parameters via POST here
                       personID: "{{ @personID }}",
                       file_record_id: pfid,
                       file_type: "contract_form",
                       dept: "your-dept",
                       file_category: "fcategory",
                       force_download: force_download
                   },
                   success: function(blob, status, xhr){
                        if (xhr.getResponseHeader('Custom-FileError')>1) {
                              alertify.error(xhr.getResponseHeader('Custom-ErrorMsg'));
                        }else{
                              //I thought this would work when viewing the PDF but it does not.
                              blob.name = xhr.getResponseHeader('Custom-FileName');
                              var fileURL = URL.createObjectURL(blob);
                              if (xhr.getResponseHeader('Custom-ForceDownload')==1) {
                                    window.open(fileURL);
                                    var link=document.createElement('a');
                                    link.href=window.URL.createObjectURL(blob);
                                    link.download=xhr.getResponseHeader('Custom-FileName');
                                    link.click();
                               }else{
                                    file_modal(fileURL,'Any Title');
                               }
                               
                           }
                      }
                   })
        });
        

        然后,为模态添加一些 javascript

        function file_modal(blob,the_title)
        {
        
            let spinner = "<div class='text-center'><i class='fa fa-spinner fa-spin fa-5x fa-fw'></i></div>";
            $("#modal_static_label").html('Loading');
            $("#modal_static .modal-body").html(spinner);
            if (blob.length > 1) {
                $("#modal_static").modal("show");
                $("#modal_static_label").html(the_title);
                $("#modal_static .modal-body").empty().append('<iframe src='+blob+' width="100%" height="500px" style="border:none;"></iframe>');
            }else{
                 $("#modal_static .modal-body").empty().html('File error');
            }
            $("#modal_static .modal-footer").html('<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>');
                
        }
        

        在服务器端,您需要发送像这样的自定义标头 [PHP]

        
        header("Content-length: $file_size");
        header("Custom-FileError: 0");
        header("Custom-FileName: ".$this->params['original_filename']);
        header("Custom-ForceDownload: ".$this->params['force_download']);
        header('Content-Type: '.$web->mime($this->full_path.$this->new_file_name));
        readfile($this->full_path.$this->new_file_name);
        

        如果用户点击“查看”,如果他们点击“下载”,模态将显示 PDF,下载窗口将显示您选择的文件名。我已经用小于 10mb 的 PDF 文件对此进行了测试,它可以按预期工作。

        我希望有人觉得这很有用。

        【讨论】:

        • ``` xhrFields: { responseType: 'blob' }, ``` 为我修好了。
        【解决方案9】:

        如果您的数据是字节数组,则不需要设置响应类型,请确保在将其传递给 blob 之前将其转换为 Uint8Array。

        例子:

        let byteArray = new Uint8Array(data)
        let file = new Blob(
          [byteArray],
          {type: 'application/pdf'}
        )
        

        它对我有用。

        如果您的数据不是byteArray,请务必将其转换为byteArray,并按照上述步骤使其工作。

        //For example if your data is base-64 encoded string.
        let byteChars = atob(data); //To decrypt data
        let dataArray = = new Array(byteChars.length);
        for(let i=0; i< byteChars.length; i++){
           dataArray[i] = byteChars.charCodeAt(i);
        }
        let byteArray = new Uint8Array(dataArray)
        let file = new Blob(
          [byteArray],
          {type: 'application/pdf'}
        )
        

        【讨论】:

          猜你喜欢
          • 2012-10-28
          • 2022-07-31
          • 2020-02-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-30
          • 1970-01-01
          相关资源
          最近更新 更多