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)运行结果如图所示

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Node.js 是一个非阻塞 I/O 的环境,能够快速地构建高效的网络应用程序。而 Express 则是 Node.js 中最受欢迎的 Web 框架之一,它为 Node.js 提供了大量的功能和模块。其中,解析 POST 请求的数据格式是 Express 最常用的功能之一。 Express 支持解析四种 POST 请求的数据格式:URL-encoded 格式、JSON 格式、Raw 格式和 multipart/form-data 格式。 1. URL-encoded 格式:这是最常用的 POST 数据格式,也是默认格式。它的数据格式类似于 URL 查询字符串,通过 key=value 的形式传递参数。Express 提供了 body-parser 中间件,可以自动将 URL-encoded 格式的请求体数据解析成 JSON 格式。 2. JSON 格式:JSON 是一种轻量级的数据交换格式,它比 XML 更加简洁易懂,也更加易于解析。如果服务端需要处理 JSON 格式的请求,可以使用 express.json() 中间件来解析请求体数据。 3. Raw 格式:Raw 格式是一种原始数据格式,不做任何编码和处理。如果客户端发送的 POST 请求数据是 Raw 格式的,服务端需要使用 body-parser 中间件提供的 raw() 方法解析请求体数据,将其转换成 Buffer 类型。 4. multipart/form-data 格式:这种格式常用于上传文件或者提交包含进制数据的表单。如果服务端需要处理 multipart/form-data 格式的请求,可以使用 multer 中间件来解析请求体数据。multer 中间件可以处理文件上传,同时还支持设置上传文件的限制条件。 综上所述,Express 中提供了多种中间件来解析不同格式的 POST 请求数据,开发者可以根据实际需求选择对应的中间件来使用。这些中间件的使用方式都非常简单,在应用程序中添加一条或几条中间件即可完成对 POST 请求数据的解析

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想想aw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值