Node.js

2. 数据上传

在实际的业务中,我们往往需要接收一些数据,比如表单数据、文件提交、Json上传、XML上传等等。

Node的http模块只对HTTP报文头部进行了解析,然后触发request事件。如果请求中还带有内容部分(比如POST报文,它具有请求头以及请求体),内容部分需要用户自行接收和解析。通过请求头的Transfer-Encoding和Content-Length可以判断请求中是否存在内容。

实践:

var http = require('http');
var hasBody = function (req) {return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
};
var server = http.createServer();
server.on('request', (req, res) => {if (hasBody(req)) {var buffers = [];req.on('data', function (chunk) {buffers.push(chunk);// res.end(Buffer.from(chunk))  //=> name=Errrl&age=20});req.on('end', function () {req.rawBody = Buffer.concat(buffers).toString();res.end(req.rawBody);    //=> name=Errrl&age=20});} else {res.end()}
}).listen(8000, () => {console.log('server is create')
})

(1)表单数据

最常见的数据提交就是通过网页的表单提交数据到服务端或者说是控制端(C层):

<form action="/upload" method="post"> <label for="username">Username:</label> <input type="text" name="username" id="username" /> <br /><input type="submit" name="submit" value="Submit" />
</form>

默认提交表单,请求头中的Content-Type字段值为application/x-www-form-urlencoded:

由于它的报文体内容与查询字符串相同:

name=Errrl&age=20

所以解析起来也非常容易:

var http = require('http');
var querystring = require('querystring')
var hasBody = function (req) {return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
};var server = http.createServer();
server.on('request', (req, res) => {if (hasBody(req)) {var buffers = [];req.on('data', function (chunk) {buffers.push(chunk);});req.on('end', function () {req.rawBody = Buffer.concat(buffers).toString();if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {req.body = querystring.parse(req.rawBody);}res.end();console.log(req.body);});} else {res.end()}
}).listen(8000, () => {console.log('server is create')
})

结果:

在后续的业务中可以直接访问req.body获取提交表单的数据。

(2)其他格式

除了提交表单数据外,常见的提交还有JSON文件和XML文件等,判断和解析它们的原理比较相似,都是依据Content-Type中的值决定,其中JSON类型的值为application/json,XML的为application/xml。

需要注意的是,在Content-Type中可能还要附带如下的编码信息:

Content-Type:application/json;charset=utf-8;

因此在做判断时,需要注意区分:

var mime = function(rq){var str = req.headers['content-type']||'';return str.split(';')[0];
}

1. JSON 文件

如果从客户端提交JSON文件内容,对于Node来说,要处理它是不需要额外的库的,操作如下:

/**处理上传的 Json 文件 */
var http = require('http');
var hasBody = function (req) {return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
};
var mime = function(req){var str = req.headers['content-type']||'';return str.split(';')[0];
}var server = http.createServer();
server.on('request', (req, res) => {if (hasBody(req)) {var buffers = [];req.on('data', function (chunk) {buffers.push(chunk);});req.on('end', function () {req.rawBody = Buffer.concat(buffers).toString();if (mime(req) === 'application/json') { try { req.body = JSON.parse(req.rawBody); } catch (e) { // 异常内容Lj响应Bad request res.writeHead(400); res.end('Invalid JSON'); return; }console.log(req.body)res.end() }});} else {res.end()}
}).listen(8000, () => {console.log('server is create')
})

2. XML 文件

解析XML文件就稍微复杂一点,需要引入第三方插件xml2js :

/**处理上传的 XML 文件 */
var http = require('http');
var xml = require('xml2js');
var hasBody = function (req) {return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
};
var mime = function (req) {var str = req.headers['content-type'] || '';return str.split(';')[0];
}var server = http.createServer();
server.on('request', (req, res) => {if (hasBody(req)) {var buffers = [];req.on('data', function (chunk) {buffers.push(chunk);});req.on('end', function () {req.rawBody = Buffer.concat(buffers).toString();if (mime(req) === 'application/xml') {xml.parseString(req.rawBody, function (err, xml) {if (err) {// 异常内容Lj响应Bad request res.writeHead(400);res.end('Invalid XML');return;}req.body = xml;console.log(req.body);res.end();});}});} else {res.end()}
}).listen(8000, () => {console.log('server is create')
})

XML文件:

<?xml version="1.0" encoding="utf-8" ?>
<root><part id = "01" name="选项一"><name>Errrl</name><age>20</age><sex>男</sex></part><part id="02" name="选项二"><name>Errl</name><age>22</age><sex>男</sex></part>
</root>

结果:

总结:

采用这种类似的方式,无论客户端提交的是什么格式的数据,我们都可以通过这种方式来判断该数据是何种类型,然后采取对应的解析方式进行解析。

(3)附件上传

除了常见的表单和特殊格式的内容提交外,还有一种比较特殊的表单,通常的表单,其内容可以通过urlencode的方式编码内容形成报文体,在发送给服务器,但是业务场景往往需要用户直接提交文件,在前端HTML代码中,特殊表单与普通表单的差异在于该表单中可以含有file类型的控件,以及需要指定表单属性enctype为multipart/form-data,如下所示:

<form action="/" method="post" enctype="multipart/form-data"> <label for="username">Username:</label> <input type="text" name="username" id="username" /> <label for="file">Filename:</label> <input type="file" name="file" id="file" /> <br /> <input type="submit" name="submit" value="Submit" />
</form>

浏览器遇到multipart/form-data表单提交时,构造的请求报文与普通表单的报文完全不同,首先请求头很特殊:

Content-Type: multipart/form-data; boundary=AaB03x
Content-Length: 18231

它代表本次提交的内容由多部分构成,其中boundary=AaB03x 指的是每每部分内容的分界符,AaB03x是随机生成的一段字符串,报文体的内容通过在它前面添加的--进行分界,报文结束时在它的前后都加上--表示结束。另外Content-Type的值必须确保报文体的长度。

接下来就看看特殊表单提交与普通表单提交的报文区别:

假设上传一个js文件,并进行文件上传,生成的报文如下:

--AaB03x\r\n
Content-Disposition: form-data; name="username"\r\n
\r\n
Jackson Tian\r\n
--AaB03x\r\n
Content-Disposition: form-data; name="file"; filename="diveintonode.js"\r\n
Content-Type: application/javascript\r\n
\r\n ... contents of diveintonode.js ...
--AaB03x--

提交普通表单,生成的报文如下:

--AaB03x\r\n
Content-Disposition: form-data; name="username"\r\n \r\n
Jackson Tian\r\n 

文件控件提交时,生成的报文如下:

--AaB03x\r\n
Content-Disposition: form-data; name="file"; filename="diveintonode.js"\r\n
Content-Type: application/javascript\r\n
\r\n ... contents of diveintonode.js ...

一旦我们知晓报文如何构成,那么解析起来就方便很多。值得注意的是:由于是文件上传,那么像普通表单、json或者xml那样先接收内容在进行解析的方式将变得不可接受。所以接收大小、格式未知的数据量时,我们要注意谨慎操作:

/**整合 */
var http = require('http');
var xml = require('xml2js');
var formidable = require('formidable')
var hasBody = function (req) {return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
};
var mime = function (req) {var str = req.headers['content-type'] || '';return str.split(';')[0];
}var server = http.createServer();
server.on('request', (req, res) => {if (hasBody(req)) {var buffers = [];req.on('data', function (chunk) {buffers.push(chunk);});req.on('end', function () {req.rawBody = Buffer.concat(buffers).toString();if (mime(req) === 'application/json') {try {req.body = JSON.parse(req.rawBody);} catch (e) {// 异常内容Lj响应Bad request res.writeHead(400);res.end('Invalid JSON');return;}console.log(req.body)res.end()} else if (mime(req) === 'application/xml') {xml.parseString(req.rawBody, function (err, xml) {if (err) {// 异常内容Lj响应Bad request res.writeHead(400);res.end('Invalid XML');return;}req.body = xml;console.log(req.body);res.end();});} else if (mime(req) === 'multipart/form-data') {var form = new formidable.IncomingForm();form.parse(req, function (err, fields, files) {req.body = fields;req.files = files;console.log(req.body);console.log(req.files)res.end();});}});} else {res.end()}
}).listen(8000, () => {console.log('server is create')
})

在此重点介绍的模块是formidable。首先话不多说 npm install formidable。它是基于流式处理解析报文,将接收到的文件写入系统的临时文件夹中,并返回对应的路径。在后期经常使用。

(4)数据库操作 ---- 操作实例

1. 连接MySql数据库

(1)MySQL的基本操作CURD

  • C:create 具体方法就是 INSERT INTO `users`(`id`,`name`) VALUES ([value-1],[value-2])
  • U:update 具体方法就是 UPDATE `users` SET `name`='value' WHERE id=1
  • R:read 具体方法就是 SELECT `id`, `name` FROM `users` WHERE 1
  • D:delete 具体方法就是 DELETE FROM `users` WHERE id=value

注意:R中的where可以加也可以不加,加上就是有条件的阅读,不加就是整体阅读。U、D一定要加上where条件如果不加死定。

(2)安装与连接数据库示例

1. 将数据库表导入到本地数据库中,并命名新的数据库文件test2

链接: https://pan.baidu.com/s/19s13smuDcTeaDTAU0UqG7Q
提取码: 94md
复制这段内容后打开百度网盘手机App,操作更方便哦

npm install mysql

创建 js 文件连接数据库,进行操作:

/* mysql.js */var mysql = require('mysql');
// 连接数据库
var connection = mysql.createConnection({host:'localhost',user:'root',password:'***',   // 填自己的database:'test2'
});
// 开启链接
connection.connect();
// 简单测试
var  mysql = 'select * from users where id=1';
connection.query(mysql,function(err,results,fields){console.log(err);console.log(results);console.log(fields);
})
connection.end(); // 注意一定要断开资源

测试:

node mysql.js 启动

结果:

null
[                             RowDataPacket {             id: 1,                    name: '路飞',               nengli: '超人系橡胶果实',        jituan: '草帽海贼团',          img: ''                   }
]
[                             FieldPacket {               catalog: 'def',           db: 'test2',              table: 'users',           orgTable: 'users',        name: 'id',               orgName: 'id',            charsetNr: 63,            length: 11,               type: 3,                  flags: 20483,             decimals: 0,              default: undefined,       zeroFill: false,          protocol41: true          },                          FieldPacket {               catalog: 'def',           db: 'test2',              table: 'users',           orgTable: 'users',        name: 'name',             orgName: 'name',          charsetNr: 33,            length: 765,              type: 253,                flags: 4097,              decimals: 0,              default: undefined,       zeroFill: false,          protocol41: true          },                          FieldPacket {               catalog: 'def',           db: 'test2',              table: 'users',           orgTable: 'users',        name: 'nengli',           orgName: 'nengli',        charsetNr: 33,            length: 765,              type: 253,                flags: 4097,              decimals: 0,              default: undefined,       zeroFill: false,          protocol41: true          },                          FieldPacket {               catalog: 'def',           db: 'test2',              table: 'users',           orgTable: 'users',        name: 'jituan',           orgName: 'jituan',        charsetNr: 33,            length: 765,              type: 253,                flags: 4097,              decimals: 0,              default: undefined,       zeroFill: false,          protocol41: true          },                          FieldPacket {               catalog: 'def',           db: 'test2',              table: 'users',           orgTable: 'users',        name: 'img',              orgName: 'img',           charsetNr: 33,            length: 765,              type: 253,                flags: 4097,              decimals: 0,              default: undefined,       zeroFill: false,          protocol41: true          }
]                             

2. 项目初始化、安装第三方模块、构建html模板

新建一个目录名称为:模块化-案例;

npm init 初始化

安装项目所需的模块:npm install art-template mysql bootstrap jquery

index.html:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Hero - Admin</title><link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css"><style>.hero-list img {width: 50px;}</style>
</head><body><header><div class="page-header container"><h1>海贼王 <small>角色管理器</small></h1></div></header><div class="container hero-list"><a class="btn btn-success pull-right" href="/add">添加英雄</a><table class="table table-hover"><thead><th>编号</th><th>名称</th><th>能力</th><th>团体</th><th>操作</th></thead><tbody id="tbody">{{each data}}<tr><td>{{$value.id}}</td><td>{{$value.name}}</td><td>{{$value.nengli}}</td><td>{{$value.jituan}}</td><td><a href="#">查看</a><a href="#">修改</a><a href="#">删除</a></td></tr>{{/each}}</tbody></table></div>
</body></html>

3. 启动项目

(1)创建http服务器并加载静态页面

http.js:

// 负责启动服务器
var http = require('http');
// 获取请求
var qingqiu = require('./http_请求处理');
var server = http.createServer();
server.listen(8080,function(err){console.log('请在浏览器中打开127.0.0.1:8080');
});qingqiu.server(server); // 将server对象传进http_请求处理.js中

http_请求处理.js:

var fs = require('fs');
var chuli = require('./http_处理数据');
// 导出数据(binds方法)
// binds方法设置监听
module.exports.server = function(server){server.on('request',function(request,response){var urls = request.url;// 获取请求路径,判断路径请求,if(urls == '/'){// 调用yewu模块获取datavar res = chuli.data;response.end(res);}else{// 接收静态资源请求并按照请求路径响应fs.readFile('.'+urls,function(err,data){response.end(data);});}})
}

http_处理数据.js:

var template = require('art-template');
template.defaults.root = './';
var data = template('./index.html',{data:123});
module.exports.data = data;

效果:

(2)动态获取数据

修改 http_处理数据.js:

// 加载引入 ./http_连接数据库.js 模块获取数据
var sql = require('./http_连接数据库');
var template = require('art-template');
template.defaults.root = './';
var res = template('./index.html',{data:sql.data});
module.exports.res = res;

http_连接数据库.js:

var mysql = require('mysql');
var connection = mysql.createConnection({host: 'localhost',user: 'root',password: '***',database: 'test2'
});connection.connect();var sql = "select * from users";connection.query(sql,function(error,res){console.log(res);exports.data = res;
});connection.end();

结果:

存在问题:通过连接数据库查找到的数据,对外导出时,导不出去。这导致模板数据为空。

解决方法:利用回调函数,将数据导出。

(3)解决问题

修改 http_处理数据.js:

// 加载引入 linkdb模块获取数据
var sql = require('./http_连接数据库');
var template = require('art-template');
template.defaults.root = './';
// 利用回调函数 获取linkdb得到的数据
sql.getdata(function(datas){// 使用模板引擎遍历解析数据// 将解析好的数据导出module.exports.res = template('./index.html',{data:datas});
});

修改 http_连接数据库.js:

var mysql = require('mysql');
// 设置连接信息
var connection = mysql.createConnection({host: '127.0.0.1',user: 'root',password: '',database: 'test2'
});
// 打开连接
connection.connect();// 将整个查的方法导出
// 因为我们需要接受一个回调函数
module.exports.getdata = function (calls) {var sql = 'select * from users';connection.query(sql, function (err, sql_data) {var da = sql_data;// 调用回调函数,将数据当做实参进行函数的回调calls(da);})connection.end();
}

结果:

4. 获取单个用户的信息

前提:修改模板 index.html:

<td><a href="/getone?id={{$value.id}}">查看</a><a href="/setone?id={{$value.id}}">修改</a><a href="/delone?id={{$value.id}}">删除</a>
</td>

(1)接受前台的请求

修改 http_请求处理.js:

var fs = require('fs');
var chuli = require('./http_处理数据');
// 导出数据(server方法)
// server方法设置监听
module.exports.server = function(server){server.on('request',function(request,response){var urls = request.url;if(urls == '/'){// 调用chuli模块获取datavar res = chuli.data;response.end(res);}else if(urls == '/get_one'){res.end(1);}else{// 接收静态资源请求并按照请求路径响应fs.readFile('.'+urls,function(err,data){response.end(data);});}})
}

但是,http_请求处理模块,无法处理前后不同类型的请求,需要我们在服务器端接收并处理客户端发送的get以及post请求;

(2)获取请求类型以及参数

GET 请求把所有的内容编码到访问路径中,POST 请求的内容全部都在请求体中。 http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件 耗时的工作,譬如上传文件。而很多时候我们可能并不需要理会请求体的内容,恶意的 POST 请求会大大消耗服务器的资源。所以 Node.js 默认是不会解析请求体的,当我们需要的时候, 只能手动来做 。

获取请求类型

var http = require('http');
var server = http.createServer();server.on('request', function(request, response) {// 获取请求类型var method = request.method;console.log(method);response.end();
});server.listen(8000, function() {console.log(' 请访问http://localhost:8000');
});

获取GET请求参数

var http = require('http');
var url = require('url');
var server = http.createServer();server.on('request', function(request, response) {// 获取请求类型var method = request.method;if(method=="GET"){//解析请求地址url_obj = url.parse(request.url,true);console.log(url_obj.pathname);console.log(url_obj.query);response.end();}else if(method=="POST"){}
});server.listen(8080, function() {console.log(' 请访问http://localhost:8080');
});

使用postman进行请求测试:

获取post请求参数

else if (method == "POST") {// url_obj = url.parse(request.url,true);// console.log(url_obj.query); //以上代码 无内容,失败// POST请求的内容全部都在请求体中
}

原因:手册中明确说明为了支持各种http应用,Node.js的HTTP API是非常底层的。它只涉及流处理与消息的解析。它把一个消息解析成消息头与消息主体,但不解析具体的消息头或者消息主体。因此我们需要查找更底层的网络实现,node中的基础网络模块net就派上用场了。

模仿上述各类上传代码:

else if (method == "POST") {// url_obj = url.parse(request.url,true);// console.log(url_obj.query); //以上代码 无内容,失败// POST请求的内容全部都在请求体中 var data = '';// net 模块中的 net.Socket 提供的data及end事件 // 绑定data事件获取数据request.on('data', function (chunk) {data += chunk;})// 绑定end事件,监听数据接受完成request.on('end', function () {// console.log(data);console.log(require('querystring').parse(data));response.end();})
}

5. 获取单个用户的信息

修改 http_请求处理.js 优先判断请求类型

var fs = require('fs');
var url = require('url');
var chuli = require('./http_处理数据');module.exports.server = function(server){server.on('request',function(request,response){var urls = url.parse(request.url,true);var method = request.method;// 获取请求路径,判断路径请求if(method == "GET"){if(urls.pathname == '/'){// 调用yewu模块获取datavar res = chuli.res;response.end(res);}else if(urls.pathname == '/get_one'){// 获取id值var id = urls.query.id;// 进行传参(关键)// ... }else{// 接收静态资源请求并按照请求路径响应fs.readFile('.'+urls.pathname,function(err,data){response.end(data);});}}else if(method == "POST"){}})
}

传参怎么传,这是关键,为了方便操作封装每一个处理数据方法:

修改 http_处理数据.js:

// 加载引入 ./http_连接数据库 模块获取数据
var url = require('url');
var sql = require('./http_连接数据库');
var template = require('art-template');
template.defaults.root = './';module.exports = {/* 在此模块中接受请求、解析请求、响应客户端 */getAll:function(req,res){sql.select(function(data){var data = template('./index.html', { data: data });/* 响应 */res.end(data);})},getOne:function(req,res){/* 交给此模块处理解析请求 */var id = url.parse(req.url,true).query.id;/* 这里又要传递参数所以对 http_连接数据库.js 每个功能进行封装 */sql.where("id="+id).select(function(data){var data = template('./new.html', { data: data });/* 响应 */res.end(data);})}}

修改 http_连接数据库.js:

// 加载第三方插件
var mysql = require('mysql');
// 连接数据库
var connection = mysql.createConnection({host:'localhost',user:'root',password:'***',database:'test2'
})
// 开启链接
connection.connect();module.exports = {where:function(wh){this.wh = wh; // this表示整个对象return this;  },select:function(callback){// 判断是否存在where条件,有就根据where条件查找,没有就整体查询if(this.wh == undefined){/* 写入sql语句 */var sql = "select * from users";}else{var sql = "select * from users where "+this.wh;}/* 根据sql语句进行查询 */connection.query(sql,function(err,sql_data){callback(sql_data);});this.wh = undefined;   // 重置where,避免this.wh会影响后面的调用}
}

修改http_请求处理.js:

var fs = require('fs');
var url = require('url');
var chuli = require('./http_处理数据');module.exports.server = function(server){server.on('request',function(request,response){var urls = url.parse(request.url,true);var method = request.method;// 获取请求路径,判断路径请求if(method == "GET"){if(urls.pathname == '/'){/* 传入request,response */chuli.getAll(request,response);}else if(urls.pathname == '/getone'){chuli.getOne(request,response);}else{// 接收静态资源请求并按照请求路径响应fs.readFile('.'+urls.pathname,function(err,data){response.end(data);});}}else if(method == "POST"){}})
}

./new.html模板:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body><table border="1" cellspacing="0" style="width: 800px;margin: 10px auto;text-align: center"><thead><th>编号</th><th>名称</th><th>能力</th><th>团体</th><th>操作</th></thead><tbody>{{each data}}<tr><td>{{$value.id}}</td><td>{{$value.name}}</td><td>{{$value.nengli}}</td><td>{{$value.jituan}}</td><td><a href="#">查看</a><a href="#">修改</a><a href="#">删除</a></td></tr>{{/each}}</tbody></table>
</body></html>

结果:

6. 链式操作原理解析

http_处理数据中链式操作数据库的原理其实就是http_连接数据库中where里的return this;既保存了数据也返回了对象本身。

7. 修改用户信息

怎么修改:

1)获取原数据(GET请求)

2)修改数据(POST请求)

前提

添加新的模板 upuser.html:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>table {margin: 0 auto;border-collapse: collapse;width: 800px;height: 500px;}td {border: 1px solid #ccc;}</style>
</head><body><form action="/setone?id={{data[0].id}}" method="post"><table><tr><td>姓名</td><td><input name="name" type="text" value="{{data[0].name}}"></td></tr><tr><td>能力</td><td><input name="nengli" type="text" value="{{data[0].nengli}}"></td></tr><tr><td>团体</td><td><input name="jituan" type="text" value="{{data[0].jituan}}"></td></tr><tr><td>上传图片</td><td><input type="file"></td></tr><tr><td></td><td><input type="submit" value="确认修改"></td></tr></table></form>
</body></html>

(1)http_请求处理.js 中添加路径

/* method=="GET" */
else if(urls.pathname == '/setone'){chuli.setone_get(request,response);
}
/* method=="POST" */
if(urls.pathname == '/setone'){chuli.setone_post(request,response);
}

(2)http_处理数据.js 中封装数据处理方法

setone_get:function(req,res){var id = url.parse(req.url, true).query.id;sql.where('id='+id).select(function(datas){var data = template('./upuser.html',{ data: datas });res.end(data);})
},
setone_post:function(req,res){var id = url.parse(req.url, true).query.id;/* 底层中获取请求体数据 */var datas = '';req.on('data',function(data){datas+=data;});req.on('end',function(){sql.where('id='+id).update(require('querystring').parse(datas),function(data){// console.log(data);  // 此处返回的是一个OkPacket对象if(data.affectedRows>=1){  // 更新行为var backstr = "<script>alert('修改成功');window.location.href='/'</script>" // 弹出窗口,并回到页面res.setHeader('Content-type','text/html;charset=utf-8');res.end(backstr);}});})
}

(3)http_连接数据库.js 中封装数据库方法

update:function(data,callback){console.log(data); //=> {name:'路飞',nengli:'超人系橡胶果实',jituan:'草帽海贼团'}var set = '';for(i in data){    //将对象组装成string字符串set+=i+"='"+data[i]+"',";}set = set.slice(0,set.length-1);   //string的slice方法,剪切// slice(初始位置,结束位置)//=> 结果:name='路飞',nengli='超人系橡胶果实',jituan='草帽海贼团'if(this.wh == undefined){console.log('滚,一定要加where');return;}else{var sql = "update users set "+set+" where "+this.wh}connection.query(sql,function(err,sql_data){callback(sql_data);})this.wh = undefined; },

8. 删除用户信息

(1)http_请求处理.js 中添加路径

/* method == 'GET' */
else if(re_url_pn == '/delone'){chuli.delone(request,response);
}

(2)http_处理数据.js 中封装数据处理方法

delone:function(req,res){var id = url.parse(req.url, true).query.id;sql.where('id='+id).delete(function(data){if(data.affectedRows>=1){   var backstr = "<script>alert('删除成功');window.location.href='/'</script>" // 弹出窗口,并回到页面res.setHeader('Content-type','text/html;charset=utf-8');res.end(backstr);}})
},

(3)http_连接数据库.js 中封装数据库方法

delete:function(callback){if(this.wh == undefined){console.log('滚,一定要加where');return;}else{var sql = "delete from users where "+this.wh;}connection.query(sql,function(err,sql_data){callback(sql_data);})this.wh = undefined;
}

9. 添加、上传用户信息

待后续,Express框架中提及.......。

前端点滴(Node.js)(五)---- 构建 Web 应用(二)数据上传相关推荐

  1. 实践案例丨教你一键构建部署发布前端和Node.js服务

    如何使用华为云服务一键构建部署发布前端和Node.js服务 构建部署,一直是一个很繁琐的过程 作为开发,最害怕遇到版本发布,特别是前.后端一起上线发布,项目又特别多的时候. 例如你有10个项目,前后端 ...

  2. 使用华为云服务一键构建部署发布前端和Node.js服务

    如何使用华为云服务一键构建部署发布前端和Node.js服务 构建部署,一直是一个很繁琐的过程 作为开发,最害怕遇到版本发布,特别是前.后端一起上线发布,项目又特别多的时候 例如你有10个项目,前后端都 ...

  3. 基于 Node.js + Koa 构建完整的 Web API (配置 ESLint 和使用 Airbnb 编码规范)

    主题内容:基于 Node.js + Koa 构建完整的 Web API (配置 ESLint 和使用 Airbnb 代码规范) 背景描述:上一篇 基于 Node.js + Koa 构建完整的 Web ...

  4. 基于 Egg.js 框架的 Node.js 服务构建之用户管理设计

    转载需经本人同意且标注本文原始地址:https://zhaomenghuan.github.io/blog/nodejs-eggjs-usersytem.html 前言 近来公司需要构建一套 EMM( ...

  5. 基于 Egg.js 框架的 Node.js 服务构建之用户管理设计 1

    前言 近来公司需要构建一套 EMM(Enterprise Mobility Management)的管理平台,就这种面向企业的应用管理本身需要考虑的需求是十分复杂的,技术层面管理端和服务端构建是架构核 ...

  6. node mongoose_如何使用Express,Mongoose和Socket.io在Node.js中构建实时聊天应用程序

    node mongoose by Arun Mathew Kurian 通过阿伦·马修·库里安(Arun Mathew Kurian) 如何使用Express,Mongoose和Socket.io在N ...

  7. 如何在Windows上安装Angular:Angular CLI,Node.js和构建工具指南

    In this tutorial, we'll learn how to install Angular CLI in Windows and use it to create an Angular ...

  8. 视频教程-20年Nodejs教程零基础入门到项目实战前端视频教程-Node.js

    20年Nodejs教程零基础入门到项目实战前端视频教程 7年的开发架构经验,曾就职于国内一线互联网公司,开发工程师,现在是某创业公司技术负责人, 擅长语言有node/java/python,专注于服务 ...

  9. 前端点滴(JS进阶)(三)---- JavaScript 两链一包

    前端点滴(JS进阶)(三)----倾尽所有 一.作用域链 1. 作用域的概念 2. 作用域链 二.面向对象编程 1. 知识回顾 2. 定义对象 (1)new 内置对象 (2)直接量语法 (3)Es5 ...

最新文章

  1. 话里话外:流程管理评价的两大要素
  2. DotNetBar for Windows Forms 11.8.0.8冰河之刃重打包版
  3. python 参数一样结果不一样_使用不同的参数多次调用同一个函数python
  4. kaios好用吗_如何评价Kai Os?
  5. 【协议分析】PC QQ协议聊天内容破解
  6. 2014新生暑假个人排位赛06 -444. 爱好和平 (数组模拟邻接表+dfs)
  7. [强网杯 2019]随便注
  8. Unity3d之AR小游戏
  9. 大学计算机基础教程第1章计算机概述总结
  10. python视频分段_Python玩转视频处理(四):视频按场景进行分割
  11. 如何用网站统计工具追踪访客来路
  12. linux mysql 超级用户_Linux下MySQL忘记超级用户口令的解决办法linux操作系统 -电脑资料...
  13. GitHub 狂飙 30K+star 面试现场, 专为程序员面试打造, 现已开源可下载
  14. ADGuard 开源广告拦截器 —— 筑梦之路
  15. QT QList<T>介绍与应用、详解、使用说明、官方手册翻译
  16. python等高线图平滑_用Matplotlib平滑等高线图中的数据
  17. 计算机视觉之图像分割——水平集方法_ACWE2001
  18. JavaWeb_Servlet_Request_Response
  19. 学遥感必读的十本专业书
  20. C4D致富经典入门到精通(八)

热门文章

  1. 两个List集合取交集、并集、差集、去重并集
  2. java开发面试 自我介绍 与 项目介绍是重点
  3. 经验:那些年,我在大学接过的外包项目
  4. 外包项目接包的四大技巧,工程师必学才能赚到钱
  5. scala之json数据解析
  6. 科学研究的预先可再现性(Preproducibility)和可再现性(Producibility)
  7. 分布式网络爬虫实例——获取静态数据和动态数据
  8. #**战神引擎架设问题总结**
  9. 无聊的冷知识,Java小小小练习,你学废了 码
  10. MD5 摘要算法应用详解