path模块
path
模块:用于处理文件路径,var path = require('path')
-
path.extname('index.html'):
获取文件的后缀名.html
-
path.basename('./conf/img/a.png'):
获取文件名a.png
-
path.join(path1, path2, ...):
连接路径,它会正确地使用当前系统的路径分隔符,Unix
系统是/
,Windows
系统是\
-
path.parse(pathStr):
返回路径字符串的对象; -
path.resolve(from, to):
将相对路径转为绝对路径。
url模块
- 解析一个域名
var url = require('url') var result = url.parse('http://www.baidu.com/')
-
result
是一个对象,如获取协议名:result.protocol --> http
-
url.parse('http://www.a.com/news?n=pfy&a=10', true):
把GET
请求的参数封装成一个对象query: { n: 'pfy', a: '10' }
-
url.format():url.parse()
的逆向操作 -
url.resolve(from, to):
拼接URL
url.resolve('http://abc.com', 'one') // http://abc.com/one url.resolve('http://abc.com/news', 'one') // http://abc.com/one
http模块
-
http
模块:提供了网络请求(客户端)和网络服务(服务端)的实现; -
http
服务端:http.Server
继承自net.Server
const server = new http.Server(); / http.createServer(); server.listen(8000, '127.0.0.1', ()=>{ // 启动成功的回调 });
- 接收请求的事件
server.on('request', (req, res) => { // request, response let url = req.url; // 请求地址,对应服务端的路由 });
-
req
本质是net.Socket + (http协议增加的内容)
,req.socket
获取客户端的socket
对象 - 设置响应头:
res.writeHead(状态码, 状态描述, 响应头)
;res.writeHead(200, 'ok', { 'Content-Type': 'text/html;charset=utf8' }); res.writeHead(301, http.STATUS_CODES[301], { --->重定向 'Content-Type': 'text/html;charset=utf8', 'Location': '/' ----> 告诉浏览器重定向的地址 });
-
res.setHeader(key, val);
也是设置响应头,会与writeHead()
设置的响应头合并,且writeHead()
设置的响应头优先;响应头的设置必须在响应数据之前; - 设置响应数据:
res.write('hello client');
- 把数据响应给客户端:
res.end(); // 本次响应数据输出完成 // 如果传递参数,内部会调用 write() res.end('hello client');
-
res.end()
表示输出,是因为response
本质上是流操作; - 通过递归查看
response
的原型链:Object.getPrototypeOf(response)
可知,response
在Stream(流)
的原型链上。
-
- 接收请求的事件
-
Http
服务的简写形式:http.createServer((req, res) => { ... }).listen(8000);
-
req - request
包含所有的请求信息,如req.url
请求接口,req.headers
请求头; -
res - response
响应对象。 - 接收请求体
let reqData = [], size = 0 req.on('data', data => { reqData.push(data) size += data.length }) req.on('end', () => { // 读取完成 // 获取到请求体的Buffer const data = Buffer.concat(reqData, size) // 结束响应 res.end() })
- 处理对 静态资源 请求,如图片
const server = http.createServer((req, response) => { if(req.headers.accept.indexOf('image/*') !== -1) { // 通过请求头判断是 图片资源,创建一个读取流 const fs = fs.createReadStream('./b.jpg') // 通过读写流管道直接写入响应体,response是一个写入流 fs.pipe(response) } else { response.end('hello node') } })
-
-
http
客户端:http.request();
- 发起一个
http
请求let client = http.request({ host: '127.0.0.1', port: 8000, // IP和端口号是TCP所必须的,其他的参数是http所需要的 protocol: 'http:', method: 'get', path: '/abc' // get请求的完整地址:http://127.0.0.1:8000/abc }, res => { // 处理服务器的响应数据 res.on('data', data => { ...//处理接收的数据,数据量比较大时,socket会分包发送,data事件多次触发 }); res.on('end', () => { //数据传输完成 }); });
- 发送的数据,并通知服务器发送完成
client.write('hello server'); // 比如post请求的参数 client.end();
- 发起一个
作为客户端
- 发送POST请求,接收响应的ZIP数据流
let params = {}
let options = {
hostname: '117.78.51.252', port: 8030, method: "POST", // POST请求
path: '/Ae/Resources/Download', // 接口
headers: { } // 如果需要,可以手动设置请求头
}
let streamlist = [];
let req = http.request(options, res => {
//res.setEncoding('utf8') //当请求的是流数据时,一定不能设置响应数据的编码
res.on('data', chunk => { // 接收数据
streamlist.push(chunk); //大数据流会分多次传输,所以先用数组保存
});
res.on('end', () => {
let data = Buffer.concat(streamlist); // 把一个buffer数组转为一个buffer
fs.writeFile('./config.zip', data, err=>{}) //把Buffer写入到文件中
});
});
req.on('error', e => { console.error(`请求遇到问题: ${e.message}`); });
// 把参数转化后,写入请求主体,两种转化方式,根据后台的获取方式进行选择
let postData = require('querystring').stringify(params) // id=1&name=Mack
let postData = JSON.stringify(params) // {"id":1,"name":"Mack"}
req.write(postData);
req.end(); // 告诉服务器,结束请求
- POST请求上传文件
let boundaryKey = "----" + new Date().getTime(); // HTTP协议
let options = {
hostname: '117.78.51.252', port: 8030, method: "POST",
path: '/Ae/Project/Upload',
headers: { // 设置数据的类型:multipart/form-data表示是上传文件
"Content-Type": "multipart/form-data; boundary=" + boundaryKey,
'Connection': "keep-alive"
}
};
let req = http.request(options, function(res) {
res.setEncoding("utf8"); // 设置响应数据的编码格式
res.on("data", chunk => { // chunk其实是一个Buffer
console.log(chunk.toString()) // 假设响应数据是简短的JSON字符串
});
res.on("end", () => { console.log("res end."); });
});
req.on('error', e => { console.log('req error: ', e) });
//开始上传:参数1表示提交的内容信息,参数2表示上传的文件列表,参数3表示请求对象
this.postFile([], [{ urlKey:"file1", /**文件名*/ urlValue: './config.zip' /**文件的路径*/ }], req);
postFile(fileInfo, fileData, req) {
const path = require('path'), fs = require('fs');
let boundaryKey = Math.random().toString(16);
let enddata = '\r\n----' + boundaryKey + '--';
let dataLength = 0, dataArr = new Array();
for (let i = 0; i < fileInfo.length; i++) {
let dataInfo = "\r\n----" + boundaryKey + "\r\n" + "Content-Disposition: form-data; name=\""
+ fileInfo[i].urlKey + "\"\r\n\r\n" + fileInfo[i].urlValue;
let dataBinary = new Buffer(dataInfo, "utf-8");
dataLength += dataBinary.length;
dataArr.push({ dataInfo });
}
let files = new Array();
for (let i = 0; i < fileData.length; i++) {
let content = "\r\n----" + boundaryKey + "\r\n" + "Content-Type: application/octet-stream\r\n" +
"Content-Disposition: form-data; name=\"" + fileData[i].urlKey + "\"; filename=\"" +
path.basename(fileData[i].urlValue) + "\"\r\n" + "Content-Transfer-Encoding: binary\r\n\r\n";
//编码为ascii时,中文会乱码
let contentBinary = new Buffer(content, 'utf-8');
files.push({ contentBinary, filePath: fileData[i].urlValue });
}
let contentLength = 0;
for (let i = 0; i < files.length; i++) {
let filePath = files[i].filePath;
if (fs.existsSync(filePath)) {
let stat = fs.statSync(filePath);
contentLength += stat.size;
} else {
contentLength += new Buffer("\r\n", 'utf-8').length;
}
contentLength += files[i].contentBinary.length;
}
req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey);
req.setHeader('Content-Length', dataLength + contentLength + Buffer.byteLength(enddata));
// 将参数发出
dataArr.forEach(({ dataInfo }) => req.write(dataInfo))
let fileindex = 0;
let doOneFile = function () {
req.write(files[fileindex].contentBinary);
let currentFilePath = files[fileindex].filePath;
if (fs.existsSync(currentFilePath)) {
let fileStream = fs.createReadStream(currentFilePath, { bufferSize: 4 * 1024 });
fileStream.pipe(req, { end: false });
fileStream.on('end', () => {
fileindex++;
if (fileindex == files.length) {
req.end(enddata);
} else {
doOneFile();
}
});
} else {
req.write("\r\n");
fileindex++;
if (fileindex == files.length) {
req.end(enddata);
} else {
doOneFile();
}
}
};
if(fileindex == files.length) {
req.end(enddata);
} else {
doOneFile();
}
}
-
request
模块 是对http
模块的GET、POST
等请求的进一步封装。
网友评论