node.js 解析post请求 方法二

前提:以前面发的node.js解析post请求方法一为模板,具体见 http://t.csdnimg.cn/ABaIn

此文我们运用第二种方法:使用第三方模块formidable对post请求进行解析。

1》代码难点 ***

在Node.js中使用formidable模块来解析POST请求主要涉及到处理文件上传和多部分表单数据(multipart/form-data)以及验证上传内容的重难点。

难点解决思路:你需要创建一个formidable的实例来处理上传的表单数据。

formidable模块会将这些文件临时存储在服务器的某个位置,你需要处理这些临时文件,可能包括移动它们到最终目标的位置。

一、具体要求:

完成注册、登录、已注册的用户表单展示、文件上传功能(也就是表单填写的用户名、密码、性别这三个信息。以及选择的图片上传功能)

二、解析post请求方法二介绍

解析post请求可以通过第三方模块进行解析,如:formidable、body-parser模块等等。此处我们使用最常用的formidable模块来进行操作

三、资源配置

(1)在终端 npm install formidable -save安装formidable模块

(2)页面配置

https://blog.csdn.net/2301_76669854/article/details/138170325里的页面配置相同。唯一不同的点在于我的注册html页面。因为  enctype="multipart/form-data"涉及到文件上传,所以在方法二:使用formidable模块解析post请求时需要添加。需要保持数据格式一致。

方法二中views文件夹下的regist.html页面如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注册</title>
  <link rel="stylesheet" href="../public/css/main.css">
</head>
<body>
  <h1>注册</h1>
  <img src="../public/images/01.png" alt=""><br>
  <form method="post" action="/doRegist" enctype="multipart/form-data"> 
    <input type="text" name="username" placeholder="用户名"><br>
    <input type="password" name="password" placeholder="密码"><br>
    <input type="radio" name="gender" value="男" checked>男
    <input type="radio" name="gender" value="女">女<br>
    <input type="file" name="head" multiple><br>  
    <!-- multiple允许选择多个文件 -->
    <input type="submit" value="注册"><br> 
  </form>
</body>
</html>

(3)在终端 npm install underscore -save安装underscore渲染模板引擎 、npm install querystring安装querystring查询模块

四、代码实现

(1)测试代码serve2.js如下:

const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');
// 导入formidable模块
const formidable = require('formidable');
// 声明一个专门存放所有用户的变量
var users;
// 导入查询参数的模块
const querystring = require('querystring')
// 导入underscore渲染模板
const _ = require('underscore');
//使用underscore渲染模板
function render(data) {
    // 读取模板内容
    let temp = fs.readFileSync(path.join(__dirname, 'views/404.html'));
    // 获取渲染函数
    let compiled = _.template(temp.toString());
    // 渲染模板
    return compiled(data);
}
//创建服务器
const server = http.createServer();
//读取文件。读取user.json存放用户数据的文件
fs.readFile(path.join(__dirname, 'data/users.json'), (err, data) => {
    if (err) {
        return;
    } else {
        users = JSON.parse(data.toString()); //如果读取正确就将读到的内容转换为一个对象存到users里
    }
})
//服务器做出请求响应
server.on('request', (req, res) => {
    let objurl = url.parse(req.url); //将url转为一个对象才能获取到它的pathname
    let pathname = objurl.pathname;
    // 对pathname做处理
    // 首先解决静态资源处理  (判断方法:startWith、indexOf、search、includes)
    // startsWith方法  以什么开头
    if (pathname.startsWith('/public')) {
        // 找到当前项目文件夹,再将相对路径转为绝对路径
        let p = path.join(__dirname, pathname);
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' })); //可以使用中文,因为现在是html页面去显示的
            } else {
                res.end(data);
            }
        })
    } else if (pathname == '/' || pathname == '/home') {
        let p = path.join(__dirname, 'views/index.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                res.end(data);
            }
        })
    } else if (pathname == '/regist') { //建一个文件夹data专门来储存数据 里面建一个users.json的文件
        let p = path.join(__dirname, 'views/regist.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                res.end(data);
            }
        })

    } else if (pathname == '/login') {
        let p = path.join(__dirname, 'views/login.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                res.end(data);
            }
        })
    } else if (pathname == '/doLogin') {
        let query = querystring.parse(objurl.query);
        let username = query.username;
        let password = query.password;
        // 声明一个变量代表我的判断结果
        let result = false;
        for (let user of users) {
            if (user.username == username && user.password == password) {
                result = true;
                break;
            }
        }
        if (result) {
            res.end(render({ msg: '登录成功' }));
        } else {
            res.end(render({ msg: '用户名或密码错误,登录失败' }));
        }
    } else if (pathname == '/doRegist' && req.method.toLowerCase() == 'post') {
        //一、创建新的IncomingForm实例
        var form = new formidable.IncomingForm({
            //uploadDir指定上传文件应储存的目录
            //keepExtensions设为true 意思是 在保存上传的文件时保留其原始拓展名。
            // multiples设为true 意思是允许上传多个文件
            uploadDir: path.join(__dirname, 'public/head/'),
            keepExtensions: true,
            multiples: true
        });
        // 二、解析请求
        form.parse(req, (err, fields, files) => { //form.parse(req,callback)方法用于解析传入的请求req中的数据,解析完成后调用回调函数
            // err 若解析错误则err是包含的错误信息
            // fields 一个包含所有文本字段的对象。这些字段是由表单中的input标签或其他文本输入元素提交的(也就是我表单填写好上传的数据)
            // files 一个包含所有上传文件的对象
            if (err) {
                console.log(err.message);
            } else {
                // 若请求解析成功则创建一个新的user对象。该对象包含从表单字段中获取的 username、password、gender、head
                let user = {
                    username: fields.username,
                    password: fields.password,
                    gender: fields.gender,
                    head: files.head[0].newFilename //files.head表示regist.html上传的文件<input type="file" name="head" multiple>中的name名为head的字段。由于files.head是一个数组,所以需要files.head[0]来表示上传的第一个head文件。newFilename是由中间件在处理文件上传保存时的新文件名。可自定义
                }
                users.push(user); //将这个 user 对象添加到 users 数组的末尾
                fs.writeFile(path.join(__dirname, 'data/users.json'), JSON.stringify(users), (err) => {
                    if (err) {
                        res.end(render({ msg: '注册失败' }));
                    } else {
                        // 注册成功
                        // 重定向(服务器端主动发起一个请求)到登录页面
                        res.writeHead(302, { 'Location': '/login' });
                        res.end();
                    }
                })
            }

        });
    }
    else if (pathname == '/list') {
        let p = path.join(__dirname, 'views/users.html');
        fs.readFile(p, (err, data) => {
            if (err) {
                res.end(render({ msg: '访问的文件不存在' }));
            } else {
                //获得渲染函数 
                let compiled = _.template(data.toString());
                // 调用渲染函数来生成html内容
                let html = compiled({ users: users }); //我们在模板里取的是users的属性,所以不能简写成users,而是users:users
                res.end(html);

            }
        })
    }
});
//启动监听
server.listen(3000, '127.0.0.1', () => {
    console.log('Server is running at http://127.0.0.1:3000');
})

(2)运行结果如图所示

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

读(用知云翻译)gaitedge论文

文章目录 前言摘要一、介绍二、相关工作2.1步态识别2.2端到端学习 三、跨域问题四、我们的框架4.1步法合成4.2步态对准模块 五、实验5.1设置5.2性能比较5.3消融实验5.4可视化 六、结论 前言 本篇博客仅为个人学习&#xff0c;全文均为知云翻译&#xff0c;如有翻译不当&#x…

Android中的屏幕刷新机制(动画视频形象说明机制)

一&#xff0c;刷新率和帧率&#xff0c;60hz和60fps的区别 在Android系统中&#xff0c;刷新率和帧率是两个不同的概念&#xff0c;它们各自在显示过程中扮演着不同的角色。以下是对它们的详细解释&#xff1a; 刷新率&#xff0c;单位是Hz&#xff0c;是指屏幕在一秒内刷新…

Python来计算 1,2,3,4 能组成多少个不相同且不重复的三位数?

我们今天的例子是 有 1&#xff0c;2&#xff0c;3&#xff0c;4 四个数字&#xff0c;它们能组成多省个互不相同且无重复的三位数&#xff1f;都分别是多少&#xff1f; 话不多说&#xff0c;我们先上代码 num 0 # 我们写了三个for循环&#xff0c;表示生成的三位数 for i…

ROS 2边学边练(41)-- 使用基于tf2_ros::MessageFilter带标记(位姿、时间...)的数据类型

前言 此篇将介绍如何利用tf2来使用传感器数据&#xff08;如单声道和立体声摄像机以及雷达&#xff09;。 假设我们创建了一只海龟叫turtle3&#xff0c;它的里程计不大好用&#xff0c;为了监视turtle3的活动轨迹&#xff0c;有台头顶摄像机被安装到该海龟的背上&#xff08;负…

arp欺骗详解

目录 arp攻击原理 arp协议简介 arp攻击原理 arp实验 实验环境 实验步骤 1、使用ipconfig命令查看靶机&#xff08;window10&#xff09;的IP地址为下一步攻击做好准备&#xff0c;这一步是模拟你获取对方IP的过程 2、使用ifconfig查询查看攻击者&#xff08;kali&#x…

【华为 ICT HCIA eNSP 习题汇总】——题目集19

1、&#xff08;多选&#xff09;以下选项中&#xff0c;FTP 常用文件传输类型有&#xff08;&#xff09;。 A、ASCII 码类型 B、二进制类型 C、EBCDIC 类型 D、本地类型 考点&#xff1a;应用层 解析&#xff1a;&#xff08;AB&#xff09; 文件传输协议&#xff08;FTP&…

Win10无法合并分区?尝试以下2种解决方法吧

若Win10无法合并分区&#xff0c;导致C盘无法扩容&#xff0c;该如何解决呢&#xff1f;本文将介绍如何利用磁盘管理工具和傲梅分区助手轻松解决这个问题&#xff01; 为什么要合并硬盘分区&#xff1f; 合并硬盘分区是指将同一硬盘上的两个分区合并成一个&#xff0c;或者将…

K8S controller编写之Informer的原理+使用[drift]

概念 核心思想&#xff08;重点&#xff09;watch-list 机制 Watch 通过 HTTP 协议与 Kubernetes API Server 建立长连接&#xff0c;接收 Kubernetes API Server 发来的资源变更事件。Watch 操作的实现机制使用 HTTP 协议的分块传输编码——当 client-go 调用 Kubernetes API…

物联网D1——建工程,配环境,注意事项

1.STLink、JLink、USB等驱动配置keil环境配置——下载芯片对应型号的包——导入库函数源文件、Core内核文件、对应芯片系统文件。 2.学会看芯片手册 3.在STM32微控制器中&#xff0c;CRH通常指的是控制寄存器高位&#xff08;Control Register High&#xff09;。 在这种情况下…

OMG 一个方法的调用改动居然优化了一倍性能!!! ConcurrentHashMap.computeIfAbsent 学习

背景 前提&#xff1a;抖音小程序有qps的监控&#xff0c;如果说qps过低就会导致小程序被下架掉。 业务代码非常的简单 一个easy的查询 但是当并非达到 20就 会发现qps降低了10倍 业务需求实现大概这么一个链路 ok 那么此前我们在认识一下 computeIfAbsent 方法&#xff08;大…

Windows使用SSH登录本机Linux虚拟机

SSH&#xff08;Secure Shell&#xff09;&#xff0c;一种网络协议&#xff0c;可以在安全外壳下实现数据传输通信&#xff0c;所以主要用于计算机间加密登录&#xff0c;可以简单理解为远程控制。除了计算机间直接互联&#xff0c;在git中也可以看到&#xff0c;常见的协议有…

opencv基础篇 ——(十一)常用照片处理函数

改善图像的亮度(illuminationChange) 用于改善光照条件不佳导致的图像对比度低下或局部过暗/过亮的问题。该函数通过模拟全局和局部光照变化&#xff0c;旨在提高图像的整体视觉质量&#xff0c;特别是在低光照条件下&#xff0c;使得图像中的重要细节更加清晰可见。 函数原型…

基于python的舞蹈经验分享交流网站django+vue

1.运行环境&#xff1a;python3.7/python3.8。 2.IDE环境&#xff1a;pycharmmysql5.7/8.0; 3.数据库工具&#xff1a;Navicat11 4.硬件环境&#xff1a;windows11/10 8G内存以上 5.数据库&#xff1a;MySql 5.7/8.0版本&#xff1b; 运行成功后&#xff0c;在浏览器中输入&am…

什么牌子内衣洗衣机好用?五种高性价比单品一览

随着科技的进步和消费者对生活质量的要求越来越高&#xff0c;很多小家电被发明出来&#xff0c;其中讨论热度较高是内衣洗衣机。它不仅方便快捷&#xff0c;还能保持衣物清洁和卫生。不过现在市面上的内衣洗衣机品牌实在太多了&#xff0c;在选购的时候让人很犹豫&#xff0c;…

日本一站式软文发稿:开启你的日本市场之旅

在当今的业界里&#xff0c;软文发稿已经成为一种被广泛采用的营销策略。不同于硬广告的直接推销&#xff0c;软文发稿注重以讲故事&#xff0c;提供有价值的信息&#xff0c;借此影响和吸引读者&#xff0c;从而间接推广企业的产品和服务。 相对于其它地区&#xff0c;日本市…

单片机排队叫号系统Proteus仿真程序 有取号键和叫号键以及重复叫号键 有注释

目录 1、前言 ​ 2、程序 资料下载地址&#xff1a;单片机排队叫号系统Proteus仿真程序 有取号键和叫号键以及重复叫号键 有注释 1、前言 系统组成&#xff1a;STC89C52RCLcd1602蜂鸣器按键 具体介绍&#xff1a; Lcd1602排队叫号系统&#xff0c;有取号显示窗和叫号显示窗…

解决clickhouse 启动报错

解决clickhouse 启动报错 Error response from daemon: driver failed programming external connectivity on endpoint clickhouse-server (b42457434cebe7d8ad024d31e4fd28eae2139bb2b5046c283bea17ce4398d5b0): Error starting userland proxy: listen tcp4 0.0.0.0:8123: …

MySQL中怎么存放一条记录

2.2.1. MySQL中一行记录是怎么存储的&#xff1f; MySQL的数据存储在那个文件&#xff1f; 每创建一个 database&#xff08;数据库&#xff09;都会在 /var/lib/mysql/ 目录里面创建一个以 database 为名的目录&#xff0c;然后保存表结构和表数据的文件都会存放在这个目录里…

【软件工程与实践】(第四版)第7章习题答案详解

写在文章开头&#xff0c;感谢你的支持与关注&#xff01;小卓不羁 第7章 一、填空题二、选择题三、简答题四、实践题 一、填空题 &#xff08;1&#xff09;发现软件的错误 &#xff08;2&#xff09;白盒法 系统的模块功能规格说明 &#xff08;3&#xff09;功能 &#xf…

如何用揿针治疗慢性咽炎?

点击文末领取揿针的视频教程跟直播讲解 在日常生活中&#xff0c;慢性咽炎极为常见&#xff0c;不致命却很恼人。一旦发作&#xff0c;你的喉咙每天都会不舒服&#xff0c;总感觉有东西堵着&#xff0c;但是呢&#xff0c;咳又咳不出来&#xff0c;咽也咽不下去&#xff0c;你…
最新文章