遇到的问题
线上地址我们访问,是无法下载的,跨域了,但是我们设置我们本地,下载就不会报错跨域,因此我们需要将这个在线地址的数据获取下来,就是二进制获取下来,然后用标签保存下来
blob介绍
BLOB
是Binary Large Object
的缩写,意为"大的二进制对象"。
对Blob对象可做如下操作
- 创建Blob URL 是指向存储在浏览器缓存或磁盘中的blob的一个引用。
- 通过
postMessage()
在窗口和工作进程间传输blob数据 - 将blob存储在客户端数据库
- 通过XMLHTTPRequest的
send()
方法将blob上传到服务器
快速入门
javascript
<script type="text/javascript">
function dowmload (url){
// 首先获取服务端的数据
const xhr = new XMLHttpRequest();
//获取图片的内容,传入url地址
xhr.open('GET', url)
//获取二进制的文件
xhr.responseType ='blob'
//发送我们请求
xhr.send()
//监听,
xhr.onload = function(){
// 加载回来的数据就在我们的blob里,xhr.response后端返回的数据
const fileBlob = xhr.response
// 将返回的blob转成url地址,就可以实现本地预览
const fileUrl = URL.createObjectURL(fileBlob)
// 实现下载,创建a标签
const elemneta = document.createElement('a')
//设置属性
elemneta.setAttribute('href',fileUrl)
elemneta.setAttribute('download','')
//放入body当中
document.body.appendChild(elemneta)
}
}
let Imgurl = 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d6f5149e490240a4be8235606f09f89b~tplv-k3u1fbpfcp-no-mark:480:400:0:0.awebp?'
dowmload(Imgurl)
</script>
下图就是我们返回的fileBlob,这样我们就拿到了图片的数据,然后就是下载下来
实战应用
实现预览pdf的功能
前端Vue部分
首先获取请求地址,设置请求,然后通过blob对象创建新的url
this.$router.resolve() 方法,生成一个路由对象
routeUrl,该方法接受一个参数对象,其中path属性指定了路由路径为'/previewPdf'
query属性指定了路由参数为**{ url: this.previewUrl },其中this.previewUrl是之前生成的用于预览PDF的URL**。
然后,通过访问routeUrl.href属性,获取生成的URL字符串,并使用window.open()方法在一个新的浏览器窗口中打开该URL。
'_blank'参数表示在新窗口中打开。
javascript
openUrl = "http://"+ window.location.host + openUrl;
// request是引入的
request({
url: openUrl,
method: 'get',
responseType: 'blob'
}).then(res => {
console.log(res)
var data = res.data;
var binaryData = [];
binaryData.push(data);
//过blob对象创建新的url
this.previewUrl = window.URL.createObjectURL(new Blob(binaryData, {type: "application/pdf;charset=utf-8"} ));
// vue路由跳转并以问号形式携带vue-pdf预览时所需要的pdf地址
const routeUrl = this.$router.resolve({
path: '/previewPdf',
query: { url: this.previewUrl, }
});
window.open(routeUrl.href, '_blank')
this.loading.close();
});
后端java部分
首先获取文件的字节数组
将字节数组转换成blob对象,并从blob对象中获取字节数组
response.getOutputStream()
方法获取响应的输出流outputStream
,该流用于将内容发送到客户端
response.setContentLength((int) blob.length())
方法设置响应内容的长度为字节数组的长度。这将告诉客户端可以期望接收到的内容长度。
然后,通过response.setContentType("application/pdf")
方法设置响应的内容类型为PDF文件。这将告诉客户端接收到的是一个PDF文件。
最后,使用outputStream.write(bytes)
将字节数组写入响应输出流,将内容发送到客户端进行下载或显示。
java
@GetMapping("/getFileByte")
public void getFileByte(HttpServletResponse response, String fileId) throws Exception {
byte[] byteArray= FmpRuntime.getFileByte(fileId);
Blob blob = new SerialBlob(byteArray);
byte[] bytes = blob.getBytes(1, (int) blob.length()); // 从Blob对象中获取字节数组
ServletOutputStream outputStream = response.getOutputStream(); // 获取响应输出流
response.setContentLength((int) blob.length()); // 设置响应内容长度
response.setContentType("application/pdf"); // 设置响应类型为PNG图片
outputStream.write(bytes); // 将字节数组写入响应输出流
outputStream.flush(); // 刷新响应输出流
}