背景
最开始,后端同学许诺给前端返回一个链接,前端只用简单的使用window.open打开即可,简直不要太简单。然而反转开始了,一天后端同学反馈没法提供给我链接(别问我为什么无法实现,我要是知道我不就成全栈了嘛),只能先将一个html页面 =>流 =>Base64编码,前端拿着这个大字符串想办法把页面完整渲染出来。
分析
通过上面的背景,我们可以简单的归纳为前端需要将Base64编码展示成一个独立页面。首先我肯定第一时间跑到网上去看看有没有作业可抄,结果当然木有。回来回想一下也正常,一般一个html格式文件给前端最简单的方式就是给链接,谁会瞎折腾转换来转换去的。
分解步骤如下:
- 转换Base64编码为Blob二进制流
- 根据二进制流转换成html实际内容的字符串文本
- 新开页面,在新页面中写入该html结构的字符串
动手环节
转换Base64编码为Blob二进制流
一般来说,前端拿到Base64编码的字符串没法直接操作,需要先转换成贴近实际文件的文件流Blob格式(如果不清楚Blob,可参考这里JS中的Blob对象)。其中需要注意关键Api是window.atob,浏览器原生方法,还有下面代码的
{ type: fileType || 'pdf' }
中的fileType是MIME类型。关键代码如下:
// base64转blob
function parseBase64ToBlob(dataUrl, fileType) {
const bstr = window.atob(dataUrl)
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: fileType || 'pdf' })
}
let base64Str = "xxxxxx";//实际base64字符串
parseBase64ToBlob(base64Str,'text/plain');//text/plain原文格式
根据二进制流转换成html实际内容的字符串文本
现在拿到Blob对象了,该怎么转换成明文(也就是开发人员能看懂的页面结构明文)呢?在得出结论前,我做了如下尝试,通过URL.createObjectURL(myBlob)
得到如下效果
blob.png
好了,这就是我们开发人员能看懂的字符串了,接下来我就在想怎么提取出来。网上一搜,这篇帖子给了我实现方案js中Blob转字符串,此步骤代码如下:
var reader = new FileReader();
reader.onload = function(event){
var content = reader.result;//实际内容就在这里
};
reader.readAsText(myBlob); //步骤一转换后的blob
新开页面,在新页面中写入该html结构的字符串
直接参考js 打开空白页,并在空白页里展现内容 代码
var html="html代码";
var open = window.open("about:blank", "_blank");
open.document.write(html);
完整代码
好了,经过上面三个步骤我们已经可以实现想要的效果,下面就是把三个步骤的代码合并一下,详细代码如下:
/**
*
* @param {*} base64Str 预览html base64编码的页面
* @param {*} fileType 转换的文件类型
*/
export function previewHtmlByBase64(base64Str, fileType) {
if (base64Str) {
const myBlob = parseBase64ToBlob(base64Str, fileType)
window.open(URL.createObjectURL(myBlob))
const reader = new FileReader()
reader.onload = function (event) {
const content = reader.result // 内容就在这里
const open = window.open('about:blank', '_blank')
open.document.write(content)
}
reader.readAsText(myBlob)
}
}
function parseBase64ToBlob(dataUrl, fileType) {
const bstr = window.atob(dataUrl)
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: fileType || 'pdf' })
}
let taxBase64 = "xxxxx";//替换成实际base64编码字符串
previewHtmlByBase64(taxBase64, 'text/plain');