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

总结:

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

相关推荐
一直在学习的小白~8 分钟前
前端项目中创建自动化部署脚本,用于 Jenkins 触发 npm run publish 来完成远程部署
前端·自动化·jenkins
Perfect—完美24 分钟前
Vue 3 事件总线详解:构建组件间高效通信的桥梁
前端·javascript·vue.js
二川bro34 分钟前
模拟类似 DeepSeek 的对话
前端·人工智能
祈澈菇凉1 小时前
Vue 中如何实现自定义指令?
前端·javascript·vue.js
sorryhc2 小时前
解读Ant Design X API流式响应和流式渲染的原理
前端·react.js·ai 编程
1024小神2 小时前
vue/react前端项目打包的时候加上时间,防止后端扯皮
前端·vue.js·react.js
拉不动的猪2 小时前
刷刷题35(uniapp中级实际项目问题-2)
前端·javascript·面试
bigcarp2 小时前
理解langchain langgraph 官方文档示例代码中的MemorySaver
java·前端·langchain
FreeCultureBoy2 小时前
从 VS Code 的插件市场下载扩展插件
前端
前端菜鸟日常2 小时前
Webpack 和 Vite 的主要区别
前端·webpack·node.js