使用pdf.js完美解决跨域显示远程pdf问题

由于公司需要在业务系统展示文服的pdf,最后折腾发现pdf存在严重跨域问题。网上也是各种跨域解决方案,但是没有哪个真正合适或者说能实现的,我参考官方demo和结合网上的一些资源,自己写了一个demo,完美运行,希望对需要的人有一些帮助。

pdf.js官网:http://mozilla.github.io/pdf.js/  


1、页面的body,这里放了一个div,将会动态添加多个canvas,也就是显示所有pdf页。


2、页面js代码块,

访问后端并获取到base64字符串

//远程文件路径,直接直接从此URL中获取到PDF,如果输入到浏览器应该会下载到一个pdf文件
        var pdfUrl = "http://localhost:8088/files/getFileById?fileId=74b8995310b141413f1a32f86e1e1ecf";

        $.ajax({
            type: "get",
            data: {"param": pdfUrl},
            async: false,
            mimeType: 'text/plain; charset=x-user-defined',
            url: "/getData",
            success: function (data) {
                var pdfData = atob(data);
                // Using DocumentInitParameters object to load binary data.
                var loadingTask = PDFJS.getDocument({data: pdfData});
                loadingTask.promise.then(function (pdf) {
                    console.log('PDF loaded');
                    var pageCountNum = pdf.numPages;
                    pdfView = pdf;
                    for (var i = 1; i <= pageCountNum; i++) {
                        addPage(i);
                    }
                }, function (reason) {
                    console.error(reason);
                });
            }
        });

根据返回的pdf信息进行遍历,生成多页pdf,其实也可以做成分页形式,但是我们的需求是便于直观阅读,并且pdf页数也不多,所以就一次性展示。

function addPage(pageNumber) {
        pdfView.getPage(pageNumber).then(function (page) {
            console.log('Page loaded');
            var scale = 1.5;
            var viewport = page.getViewport(scale);

            //在页面中创建canvas
            var canvas = document.createElement("canvas");
            canvas.id = "canvas_" + pageNumber;
            $("#canvasDiv").append(canvas);
            var context = canvas.getContext('2d');
            canvas.height = viewport.height;
            canvas.width = viewport.width;
            // Render PDF page into canvas context
            var renderContext = {
                canvasContext: context,
                viewport: viewport
            };
            var renderTask = page.render(renderContext);
            renderTask.then(function () {
                console.log('Page rendered');
            });
        });
    }


3、后端获取文件流

InputStream inputStream = null;
        try {
            String strUrl = param.trim();
            URL url = new URL(strUrl);
            //打开请求连接
            URLConnection connection = url.openConnection();
            HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
            httpURLConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            // 取得输入流,并使用Reader读取
            inputStream = httpURLConnection.getInputStream();
        } catch (IOException e) {
            log.error("", e);
        }

4、文件流转base64

            //在文件输出流上安装节点流(更大效率读取)
            bin = new BufferedInputStream(fin);
            // 创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量
            baos = new ByteArrayOutputStream();
            //创建一个新的缓冲输出流,以将数据写入指定的底层输出流
            bout = new BufferedOutputStream(baos);
            byte[] buffer = new byte[1024];
            int len = bin.read(buffer);
            while (len != -1) {
                bout.write(buffer, 0, len);
                len = bin.read(buffer);
            }
            //刷新此输出流并强制写出所有缓冲的输出字节,必须这行代码,否则有可能有问题
            bout.flush();
            byte[] bytes = baos.toByteArray();
            //sun公司的API
            return encoder.encodeBuffer(bytes).trim();

需要的朋友可以下载完整源码:https://download.csdn.net/download/u014613116/10309445


你可能感兴趣的:(java,pdf.js,跨域,pdf)