如何使用JavaScript中的PDF字节数组在浏览器中显示PDF?

7

我有一个控制器,它将响应实体以PDF的字节数组形式发送给ajax调用。现在我想在浏览器中显示它,但什么都不起作用。我尝试了旧的stackoverflow问题中的每个建议,但没有任何作用。

这是来自Spring控制器的响应:

     `  %PDF-1.4
       %����
       6 0 obj
  <</Filter/FlateDecode/Length 1983>>stream
  x�� .......... [snip rest of the output]`

这是我的Ajax代码

 $(".form").submit(function(e) {
                    var form = $(this);
                    var url = _contextPath + "pdf/" + id;
                    $.ajax({
                        type: "GET",
                        url: url,
                        data: form.serialize(),
                        datatype: "application/pdf",
                        success: function(data, textStatus, jqXHR)
                        {
                            console.log(data);
                            let pdfWindow = window.open("");
                            var bb = btoa(encodeURIComponent((data.replace(/[\u00A0-\u2666]/g, function(c) {
                                return '&#' + c.charCodeAt(0) + ';';
                            }))));
                            console.log(bb);
                            var file = new Blob([bb], {type:'application/pdf'});
                            console.log(file);
                            var fileUrl = URL.createObjectURL(file);
                            pdfWindow.document.write("<iframe width='100%' height='100%' src= '"+file+"'></iframe>");
                            /*var pdfData = btoa(unescape(encodeURIComponent(data)));
                            console.log(pdfData);
                            var pdfDataa = atob(pdfData);
                            console.log(pdfDataa);*/
                           /* var bb = btoa(encodeURIComponent((data.replace(/[\u00A0-\u2666]/g, function(c) {
                                return '&#' + c.charCodeAt(0) + ';';
                            }))));
                            console.log(bb);
                            var file = new Blob([bb], {type:'application/pdf'});
                            var fileUrl = URL.createObjectURL(file);
                            window.open(fileUrl,'', 'height=650,width=840');*/
                            //console.log(data);
                        //    window.open("data:application/pdf;base64, " + data, '', 'height=650,width=840');
                            /*var blob = new Blob( [data], { type: "application/pdf" });
                            var fileURL = URL.createObjectURL(blob);
                            var win = window.open();
                            win.document.write('<iframe src="' + fileURL + '" frameborder="0"' +
                                ' style="border:0; top:0px; left:0px; bottom:0px;' +
                                ' right:0px; width:100%; height:100%;" allowfullscreen></iframe>')*/
                           /* var datauri = 'data:application/pdf;base64,' + Base64.encode(data);
                            var win = window.open();
                            win.document.write('<iframe src="' + datauri + '" frameborder="0"' +
                                ' style="border:0; top:0px; left:0px; bottom:0px;' +
                                ' right:0px; width:100%; height:100%;" allowfullscreen></iframe>');*/
                            //var base64EncodedStr = btoa(unescape(encodeURIComponent(data)));
                            //window.open(data,"_blank","scrollbars=yes,resizable=yes");
                            //window.open("data:application/pdf," + encodeURI(data));
                           // window.open("data:application/pdf," + escape(data));
                            //window.open("data:application/pdf," + base64EncodedStr);
                          //  window.open("data:application/octet-stream;charset=utf-16le;base64,"+base64EncodedStr);

                          //  let pdfWindow = window.open("")
                           //   pdfWindow.document.write("<iframe width='100%' height='100%' src='data:application/pdf;base64, "
                           //     + blob+"'></iframe>");
                          /*  const byteArray = data;
                            const blob = new Blob([byteArray], {type: 'application/pdf'});
                            const blobURL = URL.createObjectURL(blob);
                            var win = window.open();
                            win.document.write('<iframe src="' + blobURL + '" frameborder="0"' +
                                ' style="border:0; top:0px; left:0px; bottom:0px;' +
                                ' right:0px; width:100%; height:100%;" allowfullscreen></iframe>');*/
                           /* var len = data.length;
                            var buffer = new ArrayBuffer(len);
                            var view = new Uint8Array(buffer);
                            for (var i = 0; i < len; i++) {
                                view[i] = binary.charCodeAt(i);
                            }
                            */
                            /*var base64EncodedStr = btoa(unescape(encodeURIComponent(data.toString())));
                            var pdfData = base64EncodedStr;

                            var x = window.open();
                            var iframe = x.document.createElement('iframe')
                            iframe.width = '100%'
                            iframe.height = '100%'
                            iframe.frameBorder = 0
                            iframe.style = "border: 0"
                            iframe.src = "data:application/pdf;base64, " + pdfData
                            x.document.body.appendChild(iframe);*/
                           // $('.form').unbind('submit').submit();

                        }
                    });
                    e.preventDefault();
                });

我尝试了一切但都没有成功。

这是一个GET请求?那么在文档中添加<iframe id="frame"></iframe>。然后在你的js中加入var url = _contextPath + "pdf/" + id; frame.src = url;。或者更简单的方式是,如果url是静态的,可以使用<iframe url="#the_url#"></iframe> - Kaiido
通过Ajax调用发送表单数据,因此我无法直接调用URL。我得到的响应是字节数组,所以我想在浏览器中显示它。 - user
为什么 type 被设置为 "GET" 呢?不管怎样,最简单的方法是直接将您的资源作为 Blob 获取(这意味着覆盖 jQuery 的 XHR 对象的 responseType,然后您只需要将 iframe 的 src 设置为 URL.createObjectURL(XHR.response); - Kaiido
你能展示给我如何做吗? - user
3个回答

14

在这里找到了解决方案,我从Spring控制器发送的字节数组形式如%PDF-1 %����。 因此我从Spring控制器发送Base64编码字符串,并将Base64编码字符串发送到浏览器,它可以工作。

Javascript 代码:

var arrrayBuffer = base64ToArrayBuffer(data); //data is the base64 encoded string
function base64ToArrayBuffer(base64) {
    var binaryString = window.atob(base64);
    var binaryLen = binaryString.length;
    var bytes = new Uint8Array(binaryLen);
    for (var i = 0; i < binaryLen; i++) {
        var ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    return bytes;
}
var blob = new Blob([arrrayBuffer], {type: "application/pdf"});
var link = window.URL.createObjectURL(blob);
window.open(link,'', 'height=650,width=840');

在Spring控制器中将字节数组转换为Base64编码的字符串

String encodedString = Base64.getEncoder().encodeToString(bytearrayofpdf);

如果我们没有访问服务器的权限,如何在JavaScript中将二进制字符串/字节数组转换为Base64编码的字符串? - r_zelazny
你可以直接将PDF下载为ArrayBuffer甚至Blob https://dev59.com/zpnga4cB1Zd3GeqPY3Nq#48086247 - Alex78191

3
您可以使用 pdfObject 在浏览器中查看PDF文档。只需创建一个带有ID的div,并将获取到的字节数组插入该div即可。
   PDFObject.embed(<byte array>, "#pdfObjectViewer");

要实现这一功能,您需要从pdfObject网站下载该脚本并将其包含在项目中。或者您可以使用这个CDN


小提示,它不仅仅是 <byte array>,你需要将 data:application/pdf;base64,<byte array> 作为第一个参数。 - Jonesopolis

0

$ajax({type:get,xhr:function(){var xhr = new XMLHttpRequest()if(xhr.readyState ==2){ if(xhr.status ==200){ xhr.responseType =".blob"} else{ xhr.responseType="text" } } } return xhr }, success:function(data){ var blob = new Blob([data], {type:"application/pdf"}) var url=window.URL.createObjectURL(blob) window.open(url)}})


1
你好,你的回答无法阅读。请格式化你的代码:格式化帮助。在完成后,我们可以看到你的代码是否解决了问题。谢谢。 - pierpy

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