MHTML文件如何在前端页面展示

MHTML文件如何在前端页面展示

需求背景:

目前在给证券公司做项目,但是在使用新系统的过程中,甲方还希望之前之前系统的历史记录可以看到。

最初制定的计划是项目组里面做数据的把原系统页面爬取下来,转成图片,直接给到前端即可。但是产品建议说把整个页面的html爬下来再展示更好,但是在爬取html的过程中出现了若干问题,总之最后做数据的把之前的历史记录爬成MHTML格式的给了后端,我在请求的时候后端把MHTML格式文件内容以字符串格式全部给到前端。

技术背景:

1. MHTML和HTML

特性 HTML MHTML
文件格式 纯文本文件,扩展名为.html.htm 单一文件,扩展名为.mht.mhtml
资源处理 外部资源通过链接引用 所有资源(如图片、CSS、JS)嵌入文件中
用途 用于创建和展示网页 用于保存完整网页,适合离线浏览
兼容性 所有浏览器均支持 部分浏览器支持(如IE、Edge)
文件大小 较小,因资源未嵌入 较大,因包含所有资源
离线支持 需要外部资源在线访问 支持离线浏览,资源已嵌入
分享与保存 需附带外部资源 单一文件,便于分享和保存
总结:
  • HTML:适合在线浏览,依赖外部资源。
  • MHTML:适合保存完整网页,便于离线使用和分享。

2. mhtml2html

​ 需要了解这个库的使用方式,其官网地址如下:mhtml2html - npm

3. 为什么需要 .window.document

原因 1:模拟浏览器环境
  • mhtml2html 的设计可能是为了在 Node.js 或浏览器中模拟一个独立的浏览器环境(类似 jsdomiframe),以正确解析 MHTML 文件的资源(如 CSS、图片、脚本等)。
  • 在这种情况下,生成的 convertedHTML 对象会包含一个完整的 window 对象,其内部才有 documentdocumentElement
原因 2:隔离文档作用域
  • MHTML 文件可能包含独立的 HTML、CSS 和 JavaScript 代码,需要在一个隔离的环境中运行,避免污染当前页面的全局作用域。
  • 通过将文档封装在 window 对象中,mhtml2html 实现了这种隔离。

4. innerHTML和outerHTML

特性 innerHTML outerHTML
定义 获取或设置元素内部的 HTML 内容(不包含该元素本身) 获取或设置整个元素的 HTML,包括该元素自身及其所有子元素
返回内容 返回元素内部的 HTML 字符串 返回包含当前元素标签及其内部 HTML 的完整字符串
修改行为 赋值后仅会替换元素内部的内容,不会改变元素自身 赋值后会替换整个元素(即当前元素及其所有子元素都会被更新或移除)
常见用途 用于更新或操作元素内部的内容,例如动态加载文本或子节点 用于替换、删除整个元素,或将元素及其内容导出为 HTML 字符串
注意事项 修改后元素本身的标签和属性保持不变,仅子节点内容发生变化 修改后原来的 DOM 引用可能失效,因为整个元素可能已经被新元素替换

解决思路:

1. 使用iframe展示内容
1. 首先,你可能需要一个库来解析MHTML文件。可以使用`mhtml2html`库来将MHTML转换为HTML。
2. **Blob**: 用于创建一个包含HTML内容的Blob对象。
3. **URL.createObjectURL**: 生成一个临时的URL,用于在`iframe`中加载HTML内容。

核心代码示例:

vue 复制代码
<template>
  <div>
    <!-- 使用 iframe 展示 MHTML 内容 -->
    <iframe :src="iframeSrc" width="100%" height="500px"></iframe>
  </div>
</template>

<script>
import { ref, onMounted } from "vue";
import mhtml2html from "mhtml2html";

export default {
  setup() {
    const iframeSrc = ref(""); // 用于存储 iframe 的 src

    // 加载并解析 MHTML 文件
    const loadMHTML = async () => {
      try {
        // 假设你有一个 MHTML 文件的 URL
        const mhtmlUrl = "/path/to/your/file.mhtml";

        // 获取 MHTML 文件内容
        const response = await fetch(mhtmlUrl);
        const mhtmlContent = await response.text();
        // parse解析:将 MHTML 字符串解析为对象
        const parsedMHTML = mhtml2html.parse(mhtmlContent);
		// convert, 将 解析出的 MHTML 对象转译成含有资源的 HTML
        const convertedHTML = mhtml2html.convert(parsedMHTML);

        if (!convertedHTML?.window.document?.documentElement) {
          throw new Error("HTML转换失败,未找到可用的 documentElement");
        }
        // 注意:mhtml2html.convert 返回的是一个模拟的浏览器环境,其文档对象 (document) 必须通过 .window 访问。这种设计是为了隔离 MHTML 文件的内容,确保资源解析和样式作用域的正确性。直接使用 convertedHTML.document 会失败,因为 document 并未直接暴露在返回值顶层。
        const htmlContent =
          convertedHTML.window.document.documentElement.outerHTML;
        loadingText.value = "解析成功,开始展示";
        // 创建 Blob URL
        const blob = new Blob([htmlContent], { type: "text/html" });
        iframeSrc.value = URL.createObjectURL(blob);
      } catch (error) {
        console.error("Failed to load MHTML file:", error);
      }
    };

    // 在组件挂载时加载 MHTML 文件
    onMounted(() => {
      loadMHTML();
    });

    // 在组件销毁时清理 Blob URL
    onBeforeUnmount(() => {
      if (iframeSrc.value) {
        URL.revokeObjectURL(iframeSrc.value);
      }
    });

    return {
      iframeSrc,
    };
  },
};
</script>

<style scoped>
iframe {
  border: 1px solid #ccc;
}
</style>
2. 使用v-html展示内容

​ 本来想将解析出来的html文本内容直接通过v-html展示,但是实际展示却是html字符串,所以不推荐使用这种方式。

总结:

实际上这个功能不算复杂,但是对于一些基础的前端知识先需要了解,否则会踩坑,有较长的试错时间。

相关推荐
傻小胖1 小时前
ES6 Proxy 用法总结以及 Object.defineProperty用法区别
前端·javascript·es6
Web极客码1 小时前
如何跟踪你WordPress网站的SEO变化
前端·搜索引擎·wordpress
横冲直撞de1 小时前
高版本electron使用iohook失败(使用uiohook-napi替代)
前端·javascript·electron
_Eden_1 小时前
认识Electron 开启新的探索世界一
前端·javascript·electron
~怎么回事啊~1 小时前
electron中调用C++
前端·javascript·electron
海上彼尚1 小时前
electron-vite 构建后路由失效问题
前端·javascript·electron
OpenIM1 小时前
零基础构建开源项目OpenIM桌面应用和pc web- Electron篇
前端·electron·开源
缘来是黎1 小时前
Python 进阶:生成器与上下文管理器
java·前端·python
HsuYang1 小时前
Vite源码学习(十一)——热更新(中)
前端·javascript·架构
不怕麻烦的鹿丸2 小时前
web前端录制canvas视频和video的声音,并合并成一个文件进行下载
前端·javascript·音视频·canvas