最近在使用PDF.js的过程中,需要让PDF.js预览url的pdf文件,本地文件是通过直接传入文件名的形式可以直接获取的,但是url的话会发生跨域问题,笔者这边尝试了许多方法,随后使用文件流的方式解决了,做一些分享。

问题阐述

首先看普通的显示方式,是通过本地文件的形式进行显示的。

// 文件名
let fileName = 'test.pdf'
// 调用PDF.js的控件
let pdfLink = '/plugins/pdfjs/web/viewer.html?file=' + fileName
// 更新iFrame的src路径进行显示
$('#printIframe').prop('src', pdfLink)

这样是没什么问题的
在这里插入图片描述

那么问题来了,如果传入的是url的形式呢?

// url
let fileName = 'http://XXXXXXX/XXX.pdf'
// 调用PDF.js的控件
let pdfLink = '/plugins/pdfjs/web/viewer.html?file=' + fileName
// 更新iFrame的src路径进行显示
$('#printIframe').prop('src', pdfLink)

这样的话会直接报错跨域问题
在这里插入图片描述
但是我们请求的是外部网络,无法更改服务器配置,所以这边最后使用了文件流的方式进行解决。

解决办法

首先把文件的url的请求ajax,在后台进行下载,然后把下载好的文件流传送到前台,再将文件流转换成blob形式,再将blob对象创建一个新的url,可以解析的url,随后再把新url传送给PDF.js

前端Ajax部分

// url
let fileName = 'http://XXXXXXX/XXX.pdf'
$.ajax({
        url : '/download?filename=' + encodeURIComponent(fileName),
        type: 'post',
        dataType: 'blob',
        mimeType: 'text/plain; charset=x-user-defined',
        complete: (response) => {
            // 将文件流转换成blob形式
            let rawLength = response['responseText'].length;
            let array = new Uint8Array(new ArrayBuffer(rawLength));
            for (let i = 0; i < rawLength; i++) {
                array[i] = response['responseText'].charCodeAt(i) & 0xff;
            }
            const blob = new Blob([array], {type: 'application/pdf;charset=utf-8'});
            let url = window.URL || window.webkitURL;
            // 将blob对象创建新的url
            const blobUrl = url.createObjectURL(blob);
            // 将url传送到PDF.js
            let pdfLink = '/plugins/pdfjs/web/viewer.html?file=' + blobUrl;
            // iframe画面更新
            $('#printIframe').prop('src', pdfLink);
        }
    });

后端Java部分

// 接口部分
@RequestMapping("/download")
@ResponseBody
public void fileDownload(@RequestParam("filename") String filename,
        HttpServletResponse response) throws UnsupportedEncodingException {
    // 通过网络获取文件流
    DownloadUtils.getFileStream(filename, response);
}
// 下载工具部分
// 将文件流传送到response
public static void getFileStream(String filename, HttpServletResponse response) {
    try {
        // 根据文件url下载文件
        openFile(filename, response);
    } catch (Exception e) {
        logger.error("下载失败!");
    }
}

// 通过url下载文件的方法
private static void openFile(String filePath, HttpServletResponse response) {
    // 服务器状态
    int HttpResult;
    try {
        // URL
        URL url = new URL(filePath);
        // URL连接对象
        URLConnection urlconn = url.openConnection();
        urlconn.connect();
        HttpURLConnection httpconn = (HttpURLConnection) urlconn;
        HttpResult = httpconn.getResponseCode();
        if (HttpResult != HttpURLConnection.HTTP_OK) {
            logger.error("网络连接失败");
            throw new ConnectException("网络连接失败");
        } else {
            InputStream in = urlconn.getInputStream();
            try {
                String fileName = "test.pdf";
                response.setContentType("application/pdf;charset=utf-8");
                response.addHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
                int b = 0;
                byte[] buffer = new byte[512];
                while (b != -1) {
                    b = in.read(buffer);
                    if (b != -1) {
                        response.getOutputStream().write(buffer, 0, b);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("文件取得失败");
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                    response.getOutputStream().flush();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("文件取得失败");
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        logger.error("文件取得失败");
    }
}

显示结果
在这里插入图片描述

随后发现通过url也是可以正常显示了,笔者这边亲测是没有问题,如果有问题欢迎与我留言。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐