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字符串,所以不推荐使用这种方式。

总结:

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

相关推荐
crazyme_610 分钟前
前端自学入门:HTML 基础详解与学习路线指引
前端·学习·html
撸猫79118 分钟前
HttpSession 的运行原理
前端·后端·cookie·httpsession
亦世凡华、37 分钟前
Rollup入门与进阶:为现代Web应用构建超小的打包文件
前端·经验分享·rollup·配置项目·前端分享
Bl_a_ck1 小时前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
augenstern4162 小时前
webpack重构优化
前端·webpack·重构
海拥✘2 小时前
CodeBuddy终极测评:中国版Cursor的开发革命(含安装指南+HTML游戏实战)
前端·游戏·html
寧笙(Lycode)3 小时前
React系列——HOC高阶组件的封装与使用
前端·react.js·前端框架
asqq83 小时前
CSS 中的 ::before 和 ::after 伪元素
前端·css
拖孩3 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
Hejjon3 小时前
Vue2 elementUI 二次封装命令式表单弹框组件
前端·vue.js