vue项目基于pdf.js简单在线pdf文件预览 SpringBoot 解决跨域问题,兼容移动端!
前段时间公司需要做一个PDF预览功能记录一下遇到的问题以及实现的过程PDF.js 预览远程文件跨域问题SpringBoot文件流消息头类型选择远程文件资源地址 不属于自己的管辖的范围,无法通过修改服务端处理请求头来解决问题话不多说开始了1.PDF.js 下载下载地址http://mozilla.github.io/pdf.js/getting_started/#download...
·
前段时间公司需要做一个PDF预览功能记录一下遇到的问题以及实现的过程
- PDF.js 预览远程文件跨域问题
- SpringBoot文件流消息头类型选择
- 远程文件资源地址 不属于自己的管辖的范围,无法通过修改服务端请求头来解决跨域问题
话不多说开始了
1.PDF.js 下载
下载地址 http://mozilla.github.io/pdf.js/getting_started/#download
2.拷贝PDF.js 文件里的 build 、web 文件至 vue项目里的静态文件夹statics
3.PDF.js在vue项目中的使用
这里使用iframe的形式展示pdf,因为需要跳转到新的链接才能预览
下面pdf地址的传参方式根据自身可以调整,笔者因为zuul网关做了处理才这么传参
<template>
<iframe class="prism-player" :src="url" width="100%" style=" height: 100vh;"></iframe>
</template>
<script>
import qs from 'qs'
export default {
data () {
return {
url: ''
}
},
created () {
let dataJson = {
pdfUrl : this.$route.query.url
}
let data = {
'encData': JSON.stringify(dataJson)
}
// 这里可以换成你的pdf文件地址
let url = this.$axiosHttp.axiosGetBaseURL() + "/org-v2-feedback/getFile/pdfFile?"+qs.stringify(data)
// pdf文件地址需要通过 encodeURIComponent 方法转译 因为是远程文件地址,/ 会被误解成地址一部分
// 下面这个这个viewer.html地址根据自身位置修改
this.url = './statics/pdf/web/viewer.html?file=' + encodeURIComponent(url)
}
}
</script>
下面划重点了
4.SpringBoot 文件流 实现
作者采用Java爬虫(HttpClient)的方式获取远程文件,然后以文件流的形式返回
下面是笔者自己封装的Utils
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class HttpUtils {
/**
* 通过爬虫获取文件流
* @param urlPath
* @return
*/
public static InputStream getYCFile(String urlPath) {
InputStream inputStream = null;
try {
String strUrl = urlPath.trim();
URL url = new URL(strUrl);
// 如果不需要忽略ssl证书可以不加这部分
if("https".equalsIgnoreCase(url.getProtocol())){ // 忽略https ssl证书
SslUtils.ignoreSsl();
}
//打开请求连接
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();
return inputStream;
} catch (IOException e) {
System.out.println(e.getMessage());
inputStream = null;
} catch (Exception e) {
System.out.println(e.getMessage());
inputStream = null;
}
return inputStream;
}
}
因为考虑到Https远程资源问题 需要忽略SSL证书
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SslUtils {
private static void trustAllHttpsCertificates() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager tm = new miTM();
trustAllCerts[0] = tm;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
static class miTM implements TrustManager,X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
}
/**
* 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
* @throws Exception
*/
public static void ignoreSsl() throws Exception{
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
}
springBoot 接口返回数据流就可以了
使用文件地址作为参数传入
@Controller
@RequestMapping("/getFile")
public class GetFileController {
/**
* (HttpClient)爬虫获取各种资源pdf文件 跳ssl验证
* @param response
* @param dataJson pdf 文件路径
*/
@GetMapping("/pdfFile")
public void getFile(HttpServletResponse response, String dataJson) {
if(StringUtils.isEmpty(dataJson)) {
return;
}
// 这里可根据自身的需要返回的文件类型调整消息投类型 灵活一点也可做为参数
response.setContentType("application/pdf");
JSONObject object = JSONObject.parseObject(dataJson);
String pdfUrl = object.getString("pdfUrl");
InputStream inputStream = null;
BufferedInputStream bins = null;
OutputStream outs = null;
BufferedOutputStream bouts = null;
try {
inputStream = HttpUtils.getYCFile(pdfUrl); // 使用爬虫获取文件流
if(inputStream == null) {
return;
}
bins = new BufferedInputStream(inputStream);//放到缓冲流里面
outs = response.getOutputStream(); // 获取输出流
bouts = new BufferedOutputStream(outs); //放到缓冲流里面
int bytesRead = 0;
byte[] buffer = new byte[1024];
//开始向网络传输文件流
while ((bytesRead = bins.read(buffer, 0, 1024)) != -1) {
bouts.write(buffer, 0, bytesRead);
}
bouts.flush();//这里一定要调用flush()方法
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (bins != null) {
bins.close();
}
if (outs != null) {
outs.close();
}
if (bouts != null) {
bouts.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
到这里就结束了,上面pdf地址调用接口地址就可以啦
注意:vue地址必须和springboot 地址 域名必须一致 不然又要跨域啦
如果没有办法一致 SpringBoot 服务端 处理下请求头 就可以了 至于怎么处理 百度一下
更多推荐
已为社区贡献1条内容
所有评论(0)