1.接收流
<!-- 表单是一个流数据 -->
<form action="/api/save" method="post">
<input type="text" name="abc" value="123">
<input type="submit" value="save">
</form>
后台代码
//方法1 传统的http实现
//http 代码 注意这里缺点是 buffer会一直占用内存
if (method === "POST" && url === "/api/save") {
let reqData = [];
let size = 0;
//通过流 一点一点的把水接起来
req.on('data', data => {
console.log('>>>req on', data);
reqData.push(data);
size += data.length;
});
//接完合并数据
req.on('end', function () {
console.log('end')
const data = Buffer.concat(reqData, size);
console.log('data:', size, data.toString())
res.end(`formdata:${data.toString()}`)
});
}
//方法2 koa实现
app.use(async (ctx, next) => {
console.log('body-parser.....')
const req = ctx.request.req
let reqData = [];
let size = 0;
await new Promise((resolve,reject) => {
req.on('data', data => {
console.log('>>>req on',data);
reqData.push(data);
size += data.length;
});
req.on('end', function () {
console.log('end')
const data = Buffer.concat(reqData, size);
console.log('data:', size, data.toString())
ctx.request.body = data.toString()
resolve()
});
})
await next();
});
//方法3 koa + koa-bodyparser实现
const bodyParser = require('koa-bodyparser')
//添加中间件 就可以正常接收流,自动转化
app.use(bodyParser())
router.post('/add', async (ctx, next) => {
console.log('body', ctx.request.body)//这里body已经被自动转化
ctx.body = ctx.request.body
next()
})
上传文件
index.html
<html>
<head>
<title>file test</title>
<script>
window.onload=function(){
var files = document.getElementsByTagName('input'),
len = files.length,
file;
for (var i = 0; i < len; i++) {
file = files[i];
if (file.type !== 'file') continue; // 不是文件类型的控件跳过
file.onchange = function() {
var _files = this.files;
if (!_files.length) return;
if (_files.length === 1) { // 选择单个文件
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://127.0.0.1:3000/upload');
var filePath = files[0].value;
xhr.setRequestHeader('file-name', filePath.substring(filePath.lastIndexOf('\\') + 1));
xhr.send(_files[0]);
} else { }
};
}
};
</script>
</head>
<body>
<input id='file1' type="file" />
</body>
</html>
index.js
const http = require('http')
const fs = require('fs')
const path = require('path')
const chunk = []
let size = 0
const server = http.createServer((request, response) => {
const { pathname } = require('url').parse(request.url)
if (pathname === '/upload') {
console.log('upload....')
//方法1 //利用fis文件写入,可以优化buffer 占用缓存问题。
const fileName = request.headers['file-name'] ? request.headers['file-name'] : 'abc.png'
const outputFile = path.resolve(__dirname, fileName)
const fis = fs.createWriteStream(outputFile)
request.pipe(fis)//由于是直接pipe,pipe是异步,无法确定是否输出成功
response.end()
//方法2 使用buffer确定在end 全部完成后执行后续结果
// Buffer connect
// request.on('data',data => {
// chunk.push(data)
// size += data.length
// console.log('data:',data ,size)
// })
// request.on('end',() => {
// console.log('end...')
// const buffer = Buffer.concat(chunk,size)
// size = 0
// fs.writeFileSync(outputFile,buffer)
// response.end()
// })
// 方法3 流事件写入,每次直接写入流,是写在硬盘伤的,不占用内存buffer
// request.on('data', data => {
// console.log('data:',data)
// fis.write(data)
// })
// request.on('end', () => {
// fis.end()
// response.end()
// })
}
})
server.listen(3000)