美文网首页Web前端之路让前端飞Web 前端开发
填坑笔记—Nodejs获取form-data数据

填坑笔记—Nodejs获取form-data数据

作者: 7天苹果 | 来源:发表于2017-08-14 14:36 被阅读12591次

原本的要练习cookie-session登陆的方法,顺便想要使用一下原生的xhr对象,却发现了问题,使用原生xhr对象发送post请求时,我将要发送的数据放入formData中并在后台接收,这里formData是XMLHttpRequest 2.0的新的数据类型:

XMLHttpRequest Level 2添加了一个新的接口FormData. 利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个”表单”。比起普通的ajax, 使用FormData的最大优点就是我们可以异步上传一个二进制文件。

刚开始就出错了:

前端代码:

<script>
   function register() {
       const username = document.getElementById('username').value;
       const psw = document.getElementById('psw').value;

       let formData = new FormData();
       formData.append('username', username);
       formData.append('psw', psw);
       console.log(formData);

       var xhr = new XMLHttpRequest();

       xhr.onreadystatechange = function () {
           if (xhr.readyState == 4) {
               if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                        alert(xhr.responseText);
                    } else {
                        alert("Response was unsuccessful:" + xhr.status);
                    }
                }
            };

            xhr.open("post", "/register", true);
            xhr.send(formData);
        }
    </script>
</head>
<body>
<div class="main">
        用户名:<input type="text" id="username" name="username"/>
        密码:<input type="password" id="psw" name="psw"/>
        <div class="button">
            <button class="btn btn-primary">登陆</button>
            <button class="btn btn-primary" onclick="register()">注册</button>
        </div>
</div>

想在后台接收formData的数据,返回却是个空对象。

//后台代码
const path = require('path');
const express = require('express');

const app = new express();
const bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.use(express.static('public'));

app.post('/register',(req,res)=>{
    console.log(req.body);
    res.send("ok");
});
app.listen(3000, () => {
    console.log('server started at http://localhost:3000');
});

module.exports = app;
空对象

于是在浏览器查看请求信息,发现formData的数据被放在了Request Payload中:

FormData提交格式的每个数据分三部分:

  • 第一部分也就是第一行,表示“分界线(boundary)”,我尚未深入研究这个分界线,不过,我没估计错的话,二进制大文件分隔传输时候,就是使用这个分界线。在webkit核心中,使用“——WebKitFormBoundary”加16位随机Base64位编码的字符串作为分隔边界。根据Firebug的显示,Firefox中,似乎是使用很多个"-"加时间戳进行边界分隔的。这里的边界的作用比较单纯,可能就是把表单的这两个字段作为两个独立数据流传输。
  • 第二部分也就是第二行,表示内容配置,这里都是统一的form-data(因为是FormData对象格式提交的),然后紧跟着name键值。
  • 第三部分就是第三行,表示传输的值。

那么为什么它会保存在Request Payload中而不是请求信息的body中呢?

因为HTTP POST表单请求提交时,使用的Content-Type是application/x-www-form-urlencoded,而使用原生AJAX的POST请求如果不指定请求头RequestHeader,默认使用的Content-Type是text/plain;charset=UTF-8。Content-Type不是application/x-www-form-urlencoded的POST请求是不会读取请求体数据和进行相应的参数处理的。

解决方案:

1、设置请求的Content-type字段为application/x-www-form-urlencoded

xhr.open("post", "/register", true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(formData);

此时在后台可以获取到req.body中的数据。

2、使用express的中间件connect-multiparty ,它是专门处理此类post数据相关的依赖包。
安装依赖以后在服务器端使用:

var multipart = require('connect-multiparty');

var multipartMiddleware = multipart();
app.post('/register', multipartMiddleware, function(req, res) {
    console.log('get FormData Params: ', req.body);
});

如此可以获得formData中的数据:

demo地址:https://github.com/lipeishang/JS-formData

相关文章

网友评论

    本文标题:填坑笔记—Nodejs获取form-data数据

    本文链接:https://www.haomeiwen.com/subject/pfrurxtx.html