nodejs:express + js-mdict 网页查询英汉词典,能显示图片

向 DeepSeek R1 提问:
我想写一个Web 前端网页,后台用 nodejs + js-mdict , 实现在线查询英语单词,并能显示图片

1. 项目结构

首先,创建一个项目目录,结构如下:

mydict-app/
├── public/
│   ├── index.html
│   ├── styles.css
│   └── script.js
├── server/
│   └── server.js
├── package.json
└── README.md

英汉词典文件(*.mdx , *.mdd)  已经放在 /js/testdict/ 

2. 安装依赖

在项目根目录下运行以下命令,初始化项目并安装所需的依赖:
cd mydict-app
npm init -y
npm install express
added 69 packages in 6s

npm install js-mdict
added 3 packages in 2s

3. 创建前端页面

在 public/index.html 中创建一个简单的HTML页面,包含一个输入框和三个按钮用于查询单词:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="ie=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>查询英汉词典</title><script src="jquery.js"></script><style>
/* portrait 判断为竖屏 */
@media only screen and (orientation: portrait){#lab1 {display:none;}
} 
/* landscape 判断为横屏 */ 
@media only screen and (orientation: landscape){#lab1 {display: ;}
}    </style>
</head>
<body><form name="form" id="form" action="search" method="GET" target="iframe"><label id="lab1">请输入:</label><input type="text" name="word" id="word" size="30" placeholder="请输入英文单词"><input type="submit" name="eng_han" value="英译汉"><input type="button" name="btn1" id="btn1" value="前缀查询"><input type="button" name="btn2" id="btn2" value="模糊查询"></form><p></p>
<div style="float:left; width:100%;"><div id="result" style="float:left; width:75%; height:500; border:2px;"><iframe name="iframe" id="iframe" width="100%" height="500"> </iframe></div><div id="alist" style="float:right; width:25%; height:500; border:2px;"></div>
</div><script src="script.js"></script>
</body>
</html>

 在 public 中添加一些英汉字典的样式:oalecd8e.css , oalecd8e.js , uk_pron.png, us_pron.png,
copy jquery-3.2.1.min.js pulibc\jquery.js

在 public/script.js 中编写前端逻辑:

  const iframe = $('#iframe')[0]; // 获取 iframe DOM 元素// 页面加载添加:监听iframe网页点击事件$(document).ready(function(){let listener = window.addEventListener('blur', function(){if (document.activeElement === document.getElementById('iframe')){$('iframe').contents().find('a').click(function(event){event.preventDefault();let a = $(this);if (a){let addr = a.attr('href');if (addr.indexOf('entry://')==0 && addr.indexOf('entry://#')!=0){               let word = encodeURIComponent(addr.substring(8));$.ajax({url: `/search?word=${word}`,method: 'GET',success: function (html) {// 将 HTML 内容加载到 iframe 中//$('#iframe').attr('srcdoc', html);let iframeDoc = iframe.contentDocument || iframe.contentWindow.document;if (html){// 写入 HTML 内容iframeDoc.open();iframeDoc.write(html);iframeDoc.close();}},error: function (error) {console.error('entry:请求失败:', error);}});} else if (addr.indexOf('sound://')==0){let url = "/data/" + addr.substring(8);let mp3 = new Audio(url);mp3.addEventListener("canplaythrough", (event)=> {mp3.play();});mp3.addEventListener('error', (e) => {console.error('play error:', e);});} else {console.log('href='+addr);}}});}});});// 前缀查询
$(function(){$("#btn1").click(function(){$.getJSON("/prefix?word="+$("#word").val(), function(data){let items = [];$.each(data, function(i, item){if (i<=20){items[i] = '<a href="/search?word=' +item+ '" target="iframe">' +item+ "</a><br>";}});let a = items.join('\n');if (a) $('#alist').html(a);})})
});// 模糊查询
$(function(){$("#btn2").click(function(){$.getJSON("/fuzzy?word="+$("#word").val(), function(data){let items = [];$.each(data, function(i, item){if (i<=20){items[i] = '<a href="/search?word=' +item+ '" target="iframe">' +item+ "</a><br>";}});let a = items.join('\n');if (a) $('#alist').html(a);})})
});

4. 创建后端服务器

在 server/server2.js 中编写Node.js服务器代码,使用 express 和 js-mdict 来处理查询请求:

const express = require('express');
const fs = require('fs');
const path = require('path');
const Mdict = require('js-mdict');
//console.log(Mdict);
const app = express();
const port = 8002;// 加载MDict词典文件
//const mdict = new Mdict('path/to/your/dictionary.mdx');
const mdx = new Mdict.MDX('/js/testdict/your英汉词典插图版.mdx');
const mdd = new Mdict.MDD('/js/testdict/your英汉词典插图版.mdd');
//console.log(mdd.locate('\\goods'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 提供静态文件
app.use(express.static(path.join(__dirname, '../public')));const isWord = (txt) => {// 只允许字母、/、空格、-return /^[a-zA-Z \/\-]+$/.test(txt);
};// 处理查询请求
app.get('/search', (req, res) => {let word = req.query.word;if (word) {let data = mdx.lookup(word);console.log("cha: "+ word);if(data.definition){res.send(data.definition);} else {res.status(200).send('this word not found.');}} else {res.status(400).send('error: No word input');}
});// 处理前缀查询请求
app.get('/prefix', (req, res) => {let word = req.query.word;// 检查word是否合法if (word.length>50 || !isWord(word)) {return res.status(400).send('Invalid input.');}if (word) {let alist = mdx.prefix(word);console.log("pre: "+ word);if(alist.length >0){let wordls = [];alist.forEach(function(value){wordls.push(value.keyText);});  res.json(wordls);} else {res.status(400).send('this word not found');}} else {res.status(400).send('error: No word input');}
});// 处理模糊查询请求
app.get('/fuzzy', (req, res) => {let word = req.query.word;// 检查word是否合法if (word.length>50 || !isWord(word)) {return res.status(400).send('Invalid input.');}if (word) {let alist = mdx.fuzzy_search(word,3,1);console.log("fuzzy: "+ word);if(alist.length >0){let wordls = [];alist.forEach(function(value){wordls.push(value.keyText);});  res.json(wordls);} else {res.status(400).send('this word not found');}} else {res.status(400).send('error: No word input');}
});// 指定目录
const dir1 = "/";// 实现image文件下载,不带路径
app.get('/:fileName', (req, res, next) => {let path1 = '/'; let fileName = req.params.fileName; // 捕获文件名// 检查路径中是否包含非法字符(如 ..)if (fileName.includes('..')) {return res.status(400).send('Invalid path: Path traversal is not allowed.');}//console.log(fileName);let extname = path.extname(fileName);let ext = extname.substring(1).toLowerCase();if (['bmp','gif','jpg','png'].includes(ext)){let filePath = path.join(path1, fileName);//console.log(filePath);let data = mdd.locate(filePath);if (data){console.log('key: '+ data.keyText);//console.log(Buffer.isBuffer(data.definition));if (data.definition){let binaryData = Buffer.from(data.definition, 'base64');//res.setHeader('Content-Type', 'application/octet-stream');res.set({'Content-Type': 'image','Content-Disposition': 'attachment;','Content-Length': Buffer.byteLength(binaryData)});//console.log('bytes: '+ Buffer.byteLength(binaryData));res.end(binaryData);} else {res.status(400).send('error: data.definition is null');}} else {res.status(400).send('error: data is null');}} else {res.status(400).send('filename.ext is not image');}
});// 实现image文件下载,*/是路径
app.get('/*/:fileName', (req, res, next) => {let path1 = req.params[0]; // 捕获 * 匹配的部分let fileName = req.params.fileName; // 捕获文件名// 检查路径中是否包含非法字符(如 ..)if (fileName.includes('..')) {return res.status(400).send('Invalid path: Path traversal is not allowed.');}//console.log(fileName);let extname = path.extname(fileName);let ext = extname.substring(1).toLowerCase();if (['bmp','gif','jpg','png'].includes(ext)){let filePath = path.join(dir1,path1, fileName);//console.log(filePath);let data = mdd.locate(filePath);if (data){console.log('key: '+ data.keyText);//console.log(Buffer.isBuffer(data.definition));if (data.definition){let binaryData = Buffer.from(data.definition, 'base64');//res.setHeader('Content-Type', 'application/octet-stream');res.set({'Content-Type': 'image','Content-Disposition': 'attachment;','Content-Length': Buffer.byteLength(binaryData)});//console.log('bytes: '+ Buffer.byteLength(binaryData));res.end(binaryData);} else {res.status(400).send('error: data.definition is null');}} else {res.status(400).send('error: data is null');}} else {res.status(400).send('filename.ext is not image');}
});app.listen(port, () => {console.log(`Server is running on http://localhost:${port}`);
});

5. 运行项目

在项目根目录下运行以下命令启动服务器:cd /js/mydict-app ;
node server/server2.js

然后打开浏览器,访问 http://localhost:8002,你应该可以看到一个简单的词典查询页面。输入单词并点击查询按钮,页面会显示该单词的释义,并显示插图。

6. 部署

你可以将这个应用部署到任何支持 Node.js 的服务器上。

7. 进一步优化

  • 错误处理: 在前端和后端添加更多的错误处理逻辑。

  • UI 改进: 使用前端框架(如React、Vue.js)来改进用户界面。

  • 缓存: 在后端添加缓存机制,提高查询速度。

  • 多词典支持: 支持加载多个词典文件,并提供切换词典的功能。

希望这些步骤能帮助你实现一个简单的在线英语单词查询应用!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/895910.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据分析】2.数据分析业务全流程

业务流程方法论&#xff1a;3阶段6步骤 一、课程核心内容结构 1. 方法论概述 目标&#xff1a;系统性地解决商业中的关键问题框架&#xff1a;分为三个阶段&#xff0c;每个阶段包含两个步骤适用场景&#xff1a;适用于数据分析师、业务经理等需要通过数据分析支持决策的从业…

【后端】k8s

1. 命令 1.1 获取service服务 获取集群内所有命名空间的service服务 sudo kubectl get service --all-namespaces 获取集群内指定命名空间的service服务 sudo kubectl get service -n命名空间 当权限限制到一个命名空间时,只能使用下面这个 sudo kubectl -n 命名空间 get se…

Mybatis MyBatis框架的缓存 一级缓存

1. 缓存的概念 缓存的概念 在内存中临时存储数据&#xff0c;速度快&#xff0c;可以减少数据库的访问次数。经常需要查询&#xff0c;不经常修改的数据&#xff0c;不是特别重要的数据都适合于存储到缓存中。 2.Mybatis缓存 mybatis包含了一个非常强大的查询缓存特性&#…

Linux csplit 命令实现日志文件的拆分

目录 一. 项目背景二. 通过 csplit 命令按照行数进行切割2.1 步骤分解验证2.2 直接拆分 三. 文件合并后与原文件进行diff3.1 通过 sed 命令进行合并3.2 通过 cat 命令进行合并 一. 项目背景 ⏹需要的问题 项目中需要获取某个war产生的log文件&#xff0c;由于是商用环境的log…

【EndNote】WPS 导入EndNote 21

写在前面&#xff1a;有没有人有激活码&#xff0c;跪求&#xff01; EndNote&#xff0c;在文献管理和文献引用方面很好用。写文章的时候&#xff0c;使用EndNote引入需要的文献会很方便。我目前用的WPS&#xff0c;想把EndNote的CWYW&#xff08;Cite While You Write&#…

嵌入式0xDEADBEEF

在嵌入式系统中&#xff0c;0xDEADBEEF 是一个常见的“魔数”&#xff08;magic number&#xff09;&#xff0c;通常用于调试和内存管理。它的含义和用途如下&#xff1a; 1. 调试用途 未初始化内存的标记&#xff1a;在调试时&#xff0c;0xDEADBEEF 常用于标记未初始化或已…

RT-Thread+STM32L475VET6实现红外遥控实验

文章目录 前言一、板载资源介绍二、具体步骤1. 确定红外接收头引脚编号2. 下载infrared软件包3. 配置infrared软件包4. 打开STM32CubeMX进行相关配置4.1 使用外部高速时钟&#xff0c;并修改时钟树4.2 打开定时器16(定时器根据自己需求调整)4.3 打开串口4.4 生成工程 5. 打开HW…

【HarmonyOS Next】鸿蒙应用进程和线程详解

【HarmonyOS Next】鸿蒙应用进程和线程详解 一、前言 进程的定义&#xff1a; 进程是系统进行资源分配的基本单位&#xff0c;是操作系统结构的基础。 在鸿蒙系统中&#xff0c;一个应用下会有三类进程&#xff1a; (1) 主进程&#xff0c; (2) ExtensionAbility进程&#xff…

迪威模型网:免费畅享 3D 打印盛宴,科技魅力与趣味创意并存

还在为寻找优质3D打印模型而发愁&#xff1f;快来迪威模型网&#xff08;https://www.3dwhere.com/&#xff09;&#xff0c;一个集前沿科技与无限趣味于一体的免费3D打印宝藏平台&#xff01; 踏入迪威模型网&#xff0c;仿佛开启一场未来科技之旅。其“3D打印”专区&#xff…

力扣LeetCode: 1287 有序数组中出现次数超过25%的元素

题目&#xff1a; 给你一个非递减的 有序 整数数组&#xff0c;已知这个数组中恰好有一个整数&#xff0c;它的出现次数超过数组元素总数的 25%。 请你找到并返回这个整数 示例&#xff1a; 输入&#xff1a;arr [1,2,2,6,6,6,6,7,10] 输出&#xff1a;6提示&#xff1a; …

一文看常见的消息队列对比

一、核心特性对比表 维度KafkaRabbitMQRocketMQPulsar架构设计分布式日志系统&#xff0c;依赖ZooKeeper基于AMQP协议的代理模型主从架构NameServer协调分层架构&#xff08;BrokerBookKeeper&#xff09;单机吞吐量100万 TPS5万 TPS50万 TPS150万 TPS消息延迟毫秒级&#xff…

Ubuntu USB耳机找不到设备解决

​ 一. 确定硬件连接 lsusb -t 插拔USB耳机&#xff0c;确定是否有USB识别到 二. 查看输出设备 sudo apt-get install pavucontrol pavucontrol 点击想要使用的输出设备后面的绿色选项 三. 输出设备没有USB耳机时调试 3.1 确认ALSA是否识别设备 列出ALSA播放设备&#…

[笔记.AI]如何判断模型是否通过剪枝、量化、蒸馏生成?

以下摘自与DeepSeek-R1在线联网版的对话 一、基础判断维度 技术类型核心特征验证方法剪枝模型参数减少、结构稀疏化1. 检查模型参数量是否显著小于同类标准模型1 2. 分析权重矩阵稀疏性&#xff08;如非零参数占比<30%&#xff09;4量化权重/激活值精度降低、推理速度提升1…

Redis如何解决热Key问题

目录 **如何解决 Redis 的热 Key&#xff08;Hot Key&#xff09;问题&#xff1f;****解决方案** **1. 使用多级缓存****方案** **2. 进行 Key 预分片&#xff08;Key Sharding&#xff09;****方案** **3. 使用 Redis 复制机制&#xff08;主从复制或集群&#xff09;****方案…

云计算架构学习之Ansible-playbook实战、Ansible-流程控制、Ansible-字典循环-roles角色

一、Ansible-playbook实战 1.Ansible-playbook安装软件 bash #编写yml [rootansible ansible]# cat wget.yml - hosts: backup tasks: - name: Install wget yum: name: wget state: present #检查playbook的语法 [rootansible ansible]…

【Web前端开发精品课 HTML CSS JavaScript基础教程】第二十四章课后题答案

文章目录 问题1&#xff1a;问题2&#xff1a;问题3&#xff1a; 问题1&#xff1a; 在HTML中嵌入JavaScript&#xff0c;应该使用的标签是&#xff08; &#xff09;。 选项&#xff1a; A. <style></style> B. <script></script> C. <js><…

用python进行二分法查找(python实例三十)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.代码示例 4.运行结果 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言经常使用英文关键…

Qt学习(五)自定义对话框,多窗口开发---添加设计师类, MDI多窗口开发

一 对话框 实现功能&#xff1a;打开文件&#xff0c;选择目录&#xff0c;保存文件&#xff0c;选择颜色&#xff0c;选择字体&#xff0c;输入信息&#xff0c; 消息提示框 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE na…

用 Python 实现简易的 Web 爬虫:从入门到实战

一、引言 在信息爆炸的时代,网络上蕴含着海量的数据。如果我们想要获取特定的信息,手动从网页上复制粘贴显然效率极低。这时,Web 爬虫就派上了用场。Web 爬虫是一种自动获取网页内容的程序,它可以模拟人类在浏览器中的操作,快速地抓取网页上的数据。本文将带领大家使用 Py…

机器视觉检测中,2D面阵相机和线扫相机的区别

2D面阵相机和线扫相机是工业视觉系统中常用的两种相机类型&#xff0c;各有其特点和应用场景。 2D面阵相机 特点&#xff1a; 成像方式&#xff1a;通过二维传感器一次性捕捉整个场景的图像。 分辨率&#xff1a;分辨率由传感器的像素数决定&#xff0c;常见的有百万像素到几千…