nodejs实现解析chm文件列表,无需转换为PDF文件格式,在线预览chm文件以及目录,不依赖任何网页端插件

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: nodejs实现解析chm文件列表,无需转换为PDF文件格式,在线预览chm文件以及目录,不依赖任何网页端插件



特性:

1、支持任意深度的chm文件解析

2、解析后内容结构转换为tree数据呈现

3、点击树节点可以在html实时查看数据

4、不依赖任何浏览器端插件,兼容性较好

nodejs端核心代码

const $g = global.SG.$g, fs = global.SG.fs, router = global.SG.router, xlsx = global.SG.xlsx;
module.exports = global.SG.router;
let webRootPath = 'http://127.0.0.1:9999/chm/';//测试环境chm文件根目录
//上传单个文件(all方法支持POST、GET、PUT、PATCH、DELETE传参方式)
let uploadFileName = '';//获取上传后的文件名
router.all(
    "/chm/upload",//接口路径
    $g.dir.upload(
        "./upload",//存储临时上传文件的路径
        ({ fileName, } = {}) => { uploadFileName = fileName; }).single("file"),//上传单个文件
    (req, res) => {
        // 开始解压上传的upload文件----------------------------------------
        let cp = require('child_process');
        cp.exec("reg query HKEY_CLASSES_ROOT\\360zip\\shell\\open\\command /ve", function (e, stdout, stderr) {
            let rootPath = `${__dirname.split('\\').slice(0, -3).join('\\')}`;
            let uploadFolderPath = `${rootPath}\\upload\\${uploadFileName}`;
            let targetFolderPath = `${rootPath}\\chm\\${uploadFileName}`;
            let str = stdout.match(/\"([^\"]+)\"/)[0];
            if (str) {
                // console.log('已经找到360zip程序,详细地址为:'+str);
                cp.exec(`${str} -x ${uploadFolderPath} ${targetFolderPath}`, { encoding: 'binary' }, function (e, stdout, stderr) {
                    // 遍历读取目录里面的文件----------------------------------------
                    let files = [];
                    let walker = require('walk').walk(targetFolderPath, { followLinks: false });
                    walker.on('file', function (roots, stat, next) {
                        if (stat.name.includes(`.hhc`)) {
                            let hhcFilePath = `${roots}/${stat.name}`;
                            files.push(hhcFilePath);
                            fs.readFile(hhcFilePath, 'utf-8', (err, data) => $g.json.res(req, res, "chm文件解析成功", {
                                htmPath: `${webRootPath}${uploadFileName}/`,
                                hhcFilePath: `${webRootPath}${uploadFileName}/${stat.name}`,
                                hhcData: data,
                            }, true));
                        } else next();
                    });
                    walker.on('end', function () {
                        files.length === 0 && $g.json.res(req, res, "没有找到hhc文件,请仔细检查chm文件是否正确!", { targetFolderPath }, false);
                    });
                });
            } else {
                console.log('没有找到360zip程序,无法完成解压缩功能,请在服务器端安装360zip软件!');
            }
        });
    }
);

vue前端核心代码

<template>
    <div :class="$options.name">
        <div class="sg-left " v-loading="loading">
            <!-- 树节点 -->
            <div class="tree-header">
                <!-- 树节点 -->
                <div class="tree-header">
                    <div class="sg-left ">
                        <el-tooltip popper-class="sg-el-tooltip" :enterable="false" effect="dark" :content="`支持拖拽到树上传文件`"
                            placement="top-start">
                            <el-button type="text" icon="el-icon-upload" size="mini"
                                @click="d => $refs.sgUpload.triggerUploadFile()">
                                上传chm文件
                            </el-button>
                        </el-tooltip>
                    </div>
                    <div class="sg-right ">
                    </div>
                </div>
            </div>
            <div class="tree-body" @click="treeData.length === 0 ? $refs.sgUpload.triggerUploadFile() : ''">
                <el-tree ref="tree" @current-change="current_change" :data="treeData"
                    :props="{ label: 'Name', children: 'children' }" :icon-class="'folder-tree-node'" :indent="25"
                    @node-click="nodeClick" node-key="id" :filter-node-method="filterNode" default-expand-all
                    highlight-current :default-expanded-keys="default_expanded_keys">
                    <div slot="reference" class="node-label" slot-scope="{ node, data }">
                        <label class="left" :title="node.label">
                            {{ node.label }}
                        </label>
                    </div>
                </el-tree>
                <sgUpload drag ref="sgUpload" :data="{
                    accept: `.${['chm'].join(',.')}`,
                    // actionUrl: `http://127.0.0.1:9999/api/chm/upload`,
                    actionUrl: `http://xxx.xxxxxx.cn:33/api/chm/upload`,
                    headers: {},
                }" @beforeUpload="beforeUpload" @uploadSuccess="uploadSuccess" @error="uploadError" hideUploadTray />
            </div>
        </div>
        <div class="sg-right ">
            <iframe id="iframe" ref="iframe" :src="src" frameborder="no" style="width:100%;height:100%;"></iframe>
        </div>
        <div class="hhcHTML" ref="hhcHTML" style="display: none;"> </div>
    </div>
</template>
<script>
import sgUpload from "@/vue/components/admin/sgUpload";
export default {
    name: 'chmDecode',
    components: {
        sgUpload,
    },
    data() {
        return {
            loading: false,
            htmPath: '',
            src: '',
            current_node: null,
            default_expanded_keys: [],
            treeData: [],
        }
    },
    created() {
    },
    methods: {
        // 解析hhc文件
        decodeHhcData(doms) {
            let r = [];
            let _recursion = (doms, d) => {
                [].slice.call(doms).forEach(v => {
                    let OBJECT = v.querySelector(`OBJECT`);
                    let p0 = OBJECT.querySelectorAll(`param`)[0];
                    let p1 = OBJECT.querySelectorAll(`param`)[1];
                    let obj = {
                        id: this.$g.UUID(),
                        [p0.getAttribute('name')]: p0.getAttribute('value'),//文件别名
                        [p1.getAttribute('name')]: p1.getAttribute('value'),
                        filePath: `${this.htmPath}${p1.getAttribute('value')}`,//文件路径
                    }
                    this.current_node || (this.current_node = obj);
                    d.push(obj)
                    if (OBJECT.nextElementSibling) {
                        obj.children = []
                        _recursion(OBJECT.nextElementSibling.children, obj.children)
                    }
                });
            }
            _recursion(doms, r);
            return r;
        },
        // 开始上传
        beforeUpload(d) {
            this.loading = true;
        },
        // 上传成功
        uploadSuccess(d, f) {
            this.htmPath = d.data.htmPath;
            this.$refs.hhcHTML.innerHTML = d.data.hhcData;
            this.$nextTick(() => {
                let treeData = this.decodeHhcData(this.$refs.hhcHTML.querySelectorAll(`.hhcHTML>ul>li`))
                this.treeData = treeData;
                this.loading = false;
                this.$nextTick(() => {
                    this.$refs.tree.setCurrentKey(this.current_node.id)
                    this.src = this.current_node.filePath;
                });
            });
        },
        // 上传失败
        uploadError(d, f) { this.loading = false; },
        //点击节点
        nodeClick(data) { },
        //过滤节点
        filterNode(value, data) { },
        // 树节点修改
        current_change(d) { this.src = d.filePath; },
    }
};
</script>
<style lang="scss" scoped>
.chmDecode {
    width: 100%;
    display: flex;
    flex-wrap: nowrap;
    $treeWidth: 610px;
    $treeControlWidth: 100px;
    &>.sg-left {
        width: $treeWidth;
        flex-wrap: nowrap;
        white-space: nowrap;
        flex-shrink: 0;
        .tree-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            &>.sg-left {}
            &>.sg-right {}
        }
        .tree-body {
            height: calc(100vh - 200px);
        }
    }
    &>.sg-right {
        margin-left: 20px;
        flex-grow: 1;
        height: calc(100vh - 170px);
        .baseinfo {
            width: 100%;
            height: 100%;
            overflow-x: hidden;
            overflow-y: auto;
            position: relative;
            .form-body {
                height: calc(100% - 60px);
                overflow-y: auto;
                overflow-x: hidden;
            }
            .form-footer {
                position: absolute;
                height: 70px;
                box-sizing: border-box;
                padding-top: 20px;
                width: 100%;
                display: flex;
                justify-content: space-between;
                bottom: 0;
                &>* {
                    width: 100%;
                    flex-grow: 1;
                }
            }
        }
    }
}
</style>


相关文章
|
1月前
|
人工智能 编解码 文字识别
OCRmyPDF:16.5K Star!快速将 PDF 文件转换为可搜索、可复制的文档的命令行工具
OCRmyPDF 是一款开源命令行工具,专为将扫描的 PDF 文件转换为可搜索、可复制的文档。支持多语言、图像优化和多核处理。
298 17
OCRmyPDF:16.5K Star!快速将 PDF 文件转换为可搜索、可复制的文档的命令行工具
|
27天前
|
文字识别 Serverless 开发工具
【全自动改PDF名】批量OCR识别提取PDF自定义指定区域内容保存到 Excel 以及根据PDF文件内容的标题来批量重命名
学校和教育机构常需处理成绩单、报名表等PDF文件。通过OCR技术,可自动提取学生信息并录入Excel,便于统计分析和存档管理。本文介绍使用阿里云服务实现批量OCR识别、内容提取、重命名及导出表格的完整步骤,包括开通相关服务、编写代码、部署函数计算和设置自动化触发器等。提供Python示例代码和详细操作指南,帮助用户高效处理PDF文件。 链接: - 百度网盘:[链接](https://pan.baidu.com/s/1mWsg7mDZq2pZ8xdKzdn5Hg?pwd=8866) - 腾讯网盘:[链接](https://share.weiyun.com/a77jklXK)
77 5
|
1月前
|
文字识别 BI
【图片型PDF】批量识别扫描件PDF指定区域局部位置内容,将识别内容导出Excel表格或批量改名文件,基于阿里云OCR对图片型PDF识别改名案例实现
在医疗和政务等领域,图片型PDF文件(如病历、报告、公文扫描件)的处理需求广泛。通过OCR技术识别这些文件中的文字信息,提取关键内容并保存为表格,极大提高了信息管理和利用效率。本文介绍一款工具——咕嘎批量OCR系统,帮助用户快速处理图片型PDF文件,支持区域识别、内容提取、导出表格及批量改名等功能。下载工具后,按步骤选择处理模式、进行区域采样、批量处理文件,几分钟内即可高效完成数百个文件的处理。
155 8
|
2月前
|
机器学习/深度学习 人工智能 文字识别
Zerox:AI驱动的万能OCR工具,精准识别复杂布局并输出Markdown格式,支持PDF、DOCX、图片等多种文件格式
Zerox 是一款开源的本地化高精度OCR工具,基于GPT-4o-mini模型,支持PDF、DOCX、图片等多种格式文件,能够零样本识别复杂布局文档,输出Markdown格式结果。
210 4
Zerox:AI驱动的万能OCR工具,精准识别复杂布局并输出Markdown格式,支持PDF、DOCX、图片等多种文件格式
|
2月前
node环境之当我们遇到需要付费的依赖库@fortawesome/fontawesome-pro导致npm install无法进行怎么办-fontawesome-pro依赖库
node环境之当我们遇到需要付费的依赖库@fortawesome/fontawesome-pro导致npm install无法进行怎么办-fontawesome-pro依赖库
60 3
node环境之当我们遇到需要付费的依赖库@fortawesome/fontawesome-pro导致npm install无法进行怎么办-fontawesome-pro依赖库
|
3月前
|
人工智能 文字识别 数据挖掘
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
MarkItDown 是微软开源的多功能文档转换工具,支持将 PDF、PPT、Word、Excel、图像、音频等多种格式的文件转换为 Markdown 格式,具备 OCR 文字识别、语音转文字和元数据提取等功能。
536 9
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
|
5天前
|
资源调度 JavaScript 前端开发
前端开发必备!Node.js 18.x LTS保姆级安装教程(附国内镜像源配置)
本文详细介绍了Node.js的安装与配置流程,涵盖环境准备、版本选择(推荐LTS版v18.x)、安装步骤(路径设置、组件选择)、环境验证(命令测试、镜像加速)及常见问题解决方法。同时推荐开发工具链,如VS Code、Yarn等,并提供常用全局包安装指南,帮助开发者快速搭建高效稳定的JavaScript开发环境。内容基于官方正版软件,确保合规性与安全性。
56 23
|
1月前
|
弹性计算 JavaScript 前端开发
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
Node.js 是一种高效的 JavaScript 运行环境,基于 Chrome V8 引擎,支持在服务器端运行 JavaScript 代码。本文介绍如何在阿里云上一键部署 Node.js 环境,无需繁琐配置,轻松上手。前提条件包括 ECS 实例运行中且操作系统为 CentOS、Ubuntu 等。功能特点为一键安装和稳定性好,支持常用 LTS 版本。安装步骤简单:登录阿里云控制台,选择扩展程序管理页面,安装 Node.js 扩展,选择实例和版本,等待创建完成并验证安装成功。通过阿里云的公共扩展,初学者和经验丰富的开发者都能快速进入开发状态,开启高效开发之旅。
|
23天前
|
JavaScript 前端开发 数据可视化
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
40 2
【01】Cocos游戏开发引擎从0开发一款游戏-cocos环境搭建以及配置-Cocos Creator软件系统下载安装-node环境-优雅草卓伊凡
|
1月前
|
弹性计算 JavaScript 前端开发
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!
一键安装!阿里云新功能部署Nodejs环境到ECS竟然如此简单!

热门文章

最新文章

推荐镜像

更多