废话不多说,直接上干货
node.js服务端代码
'use strict';
import express from 'express'
import path from 'path';
import fs from 'fs'
import mineType from 'mime-types'
// import upcom from '../../controller/commond/upcommond.js'
var router = express.Router()
// router.get('/upcom', upcom);
router.get('/fileStr', (req, res, next) => {
// res.send('heoooooo')path.join(__dirname, "./test.html")
// let data = fs.readFileSync('./static/b.pdf');
// data = new Buffer(data).toString('base64');
// let base64 = 'data:' + mineType.lookup('./static/b.pdf') + ';base64,' + data;
// res.send({
// msg:'成功',
// url:base64
// })
//有效代码
res.set({
"Content-type":"application/octet-stream",
"Content-Disposition":"attachment;filename=test_2.pdf"
});
fs.readFile("./static/b.pdf",function(err,data){
if(err){
console.log(err)
}else{
res.send(data)
}
})
//有效代码结束
//下面的是读取文件的另一种方式
let readStream = fs.createReadStream('./static/b.pdf', { encoding: 'utf8' });
var fileData = '';
//读取文件发生错误事件
readStream.on('error', (err) => {
console.log('发生异常:', err);
});
//已打开要读取的文件事件
readStream.on('open', (fd) => {
console.log('文件已打开:');
});
//文件已经就位,可用于读取事件
readStream.on('ready', () => {
console.log('文件已准备好..');
});
//文件读取中事件·····
readStream.on('data', (chunk) => {
console.log('读取文件数据:');
fileData += chunk;
});
//文件读取完成事件
readStream.on('end', (data) => {
console.log('读取已完成..');
// res.send(fileData)
});
//文件已关闭事件
readStream.on('close', () => {
console.log('文件已关闭!');
});
});
export default router
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p onclick="clickme()" ">点我预览</p>
</body>
<script src="https://code.jquery.com/jquery-3.1.1.min.js "></script>
<script>
var allDownload = function(formData, url, name) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function() {
// 请求完成
console.log(this)
if (this.status === 200) {
// 返回200
var blob = this.response;
var url = window.URL || window.webkitURL || window.mozURL;
window.open('http://localhost:8888/web/viewer.html?file='+url.createObjectURL(blob))
//下面没用
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function(e) {
// // // 转换完成,创建一个a标签用于下载
// // // var a = document.createElement("a");
// // // a.download = name + ".xlsx";
// // // a.href = e.target.result;
// // // $("body").append(a); // 修复firefox中无法触发click
// // // a.click();
// // // resolve(200)
// // // $(a).remove();
// window.open('http://localhost:8888/ajax.html?file='+url.createObjectURL(blob))
};
}
};
// 发送ajax请求
xhr.send(formData);
})
};
function clickme() {
console.log(123)
allDownload({},'http://localhost:3000/filelist/fileStr','w')
};
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
</script>
</html>
用到了pdf.js插件
讲一下思路,在没有文件服务器的情况下,后端给前端传一个二进制的文件流,前端通过文件流和pdf.js插件来完成预览,下载就好说了,直接将流地址通过a标签下载就行。如果有文件服务器oss 或者七牛的话就太简单了。直接将文件地址扔给服务器就好,浏览器是直接支持打开pdf文件的。
当我们触发预览函数的时候,后台给我们返回blob文件流,此时我们创建bloburl,跳转到pdf.插件提供的web文件夹下的viewer.html文件,并附上我们创建好的blob的地址就可以实现预览了
这两个文件夹下载请戳这里。