内容:

1.文件上传基础

2.node文件处理机制

3.用流实现文件上传

1.文件上传基础

前端代码:

 <form action="localhost:8080/" method="post" enctype="multipart/form-data">
<input type="file" name="f1">
<input type="submit" value="上传文件">
</form> 注意:
上传文件时表单中的enctype="multipart/form-data"必须要写
input(file)必须要有name

后端代码:

 const http = require('http');
const uuid = require('uuid/v4');
const fs = require('fs') let server_post = http.createServer((req, res) => {
let arr = []; req.on('data', data => {
arr.push(data);
});
req.on('end', () => {
let data = Buffer.concat(arr);
// console.log(data) //data
//解析二进制文件上传数据
let post = {};
let files = {};
if (req.headers['content-type']) {
let str = req.headers['content-type'].split('; ')[1];
if (str) {
let boundary = '--' + str.split('=')[1]; //1.用"分隔符切分整个数据"
let arr = (data.toString()).split(boundary); //2.丢弃头尾两个数据
arr.shift();
arr.pop(); //3.丢弃掉每个数据头尾的"\r\n"
arr = arr.map(buffer => buffer.slice(2, buffer.length - 2)); //4.每个数据在第一个"\r\n\r\n"处切成两半
arr.forEach(buffer => {
let n = buffer.indexOf('\r\n\r\n'); let disposition = buffer.slice(0, n);
let content = buffer.slice(n + 4); disposition = disposition.toString(); if (disposition.indexOf('\r\n') === -1) {
//普通数据
//Content-Disposition: form-data; name="user"
content = content.toString(); let name = disposition.split('; ')[1].split('=')[1];
name = name.substring(1, name.length - 1); post[name] = content;
} else {
//文件数据
/*Content-Disposition: form-data; name="f1"; filename="a.txt"\r\n
Content-Type: text/plain*/
let [line1, line2] = disposition.split('\r\n');
let [, name, filename] = line1.split('; ');
let type = line2.split(': ')[1]; name = name.split('=')[1];
name = name.substring(1, name.length - 1);
filename = filename.split('=')[1];
filename = filename.substring(1, filename.length - 1); let path = `upload/${uuid().replace(/\-/g, '')}`; fs.writeFile(path, content, err => {
if (err) {
console.log('文件写入失败', err);
} else {
files[name] = {filename, path, type};
console.log(files);
}
});
}
}); //5.完成
console.log(post);
}
} res.end();
});
});
server_post.listen(8080);

2.node文件处理机制

node文件上传从根本上来说就两种方法:

(1)最基础原始的方法

使用fs中的readFile和writeFile实现(读取完上传的文件后保存)

这样做有弊端:

  • 只能等到所有数据都到达了才开始处理
  • readFile先把所有数据全读到内存中,然后回调:
  • 1.极其占用内存
  • 2.资源利用极其不充分

(2)更好的方法

使用流,收到一部分数据就直接解析一部分,实例见后面的文件上传实例

3.用流实现文件上传

(1)流

三种流:

  • 读取流  -->  fs.createReadStream、req
  • 写入流  -->  fs.createWriteStream、res
  • 读写流  -->  压缩、加密

(2)流实现读写文件

 const fs = require('fs')

 let rs = fs.createReadStream('1.txt')       // 读取流
let ws = fs.createWriteStream('2.txt') // 写入流 rs.pipe(ws) // 异常处理
rs.on('error', function (error) {
console.log('读取失败!')
}) // 读取完成 及 写入完成
rs.on('end', function () {
console.log('读取完成!')
}) ws.on('finish', function () {
console.log('写入完成!')
})

注:1.txt应该在同级目录下

(3)用流实现上传文件核心代码

 /**
* [saveFileWithStream description]
* @param {String} filePath [文件路径]
* @param {Buffer} readData [Buffer 数据]
*/
static saveFile(filePath, fileData) {
return new Promise((resolve, reject) => {
// 块方式写入文件
const wstream = fs.createWriteStream(filePath); wstream.on('open', () => {
const blockSize = 128;
const nbBlocks = Math.ceil(fileData.length / (blockSize));
for (let i = 0; i < nbBlocks; i += 1) {
const currentBlock = fileData.slice(
blockSize * i,
Math.min(blockSize * (i + 1), fileData.length),
);
wstream.write(currentBlock);
} wstream.end();
});
wstream.on('error', (err) => { reject(err); });
wstream.on('finish', () => { resolve(true); });
});
} // 实际调用的时候,如下:
try {
await saveFileWithStream(filePath, fileData); // 这里的fileData是Buffer类型
} catch (err) {
console.log(err.stack);
}

node进阶之用流实现上传文件的更多相关文章

  1. [Node.js] 使用File API 异步上传文件

    原文地址:http://www.moye.me/2014/11/05/html5-filereader/ 最近在做一个网盘的项目,不出意外的涉及到大文件的上传,那么问题来了:如何实时的显示文件上传的进 ...

  2. js上传文件获取文件流

    上传文件获取文件流 <div> 上传文件 : <input type="file" name = "file" id = "file ...

  3. 记录一次node中台转发表单上传文件到后台过程

    首发掘金 记录一次node中台转发表单上传文件到后台过程 本篇跟掘金为同一个作者leung   公司几个项目都是三层架构模式即前台,中台(中间层),后台.前台微信端公众号使用vue框架,后台管理前端使 ...

  4. PHP流式上传和表单上传(美图秀秀)

    最近需要开发一个头像上传的功能,找了很多都需要授权的,后来找到了美图秀秀,功能非常好用. <?php /** * Note:for octet-stream upload * 这个是流式上传PH ...

  5. Asp.net上传文件后台通过二进制流发送到其他Url保存

    实际情况一般有单独的站点存放静态文件,比如图片.office文档等.A站点的操作需要上传文件到B站点, 下面介绍一种方法通过System.Net.WebClient类的UploadData方法 . u ...

  6. 上传文件报错System.Net.ProtocolViolationException: 必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]GetResponse。

    在上传文件的时候报错. 错误: System.Net.ProtocolViolationException: 必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]GetRe ...

  7. Nodejs学习笔记(八)--- Node.js + Express 实现上传文件功能(felixge/node-formidable)

    目录 前言 formidable简介 创建项目并安装formidable 实现上传功能 运行结果 部分疑惑解析 写在之后 前言 前面讲了一个构建网站的示例,这次在此基础上再说说web的常规功能---- ...

  8. c#上传文件(二)使用文件流保存文件

    1.html代码: <asp:FileUpload runat="server" ID="UpLoadFile"/> <asp:Button ...

  9. IOS--工作总结--post上传文件(以流的方式上传)

    1.添加协议 <NSURLConnectionDelegate> 2.创建 @property (nonatomic,retain) NSURLConnection* aSynConnec ...

随机推荐

  1. TJU Problem 2520 Quicksum

    注意: for (int i = 1; i <= aaa.length(); i++) 其中是“ i <= ",注意等号. 原题: 2520.   Quicksum Time L ...

  2. Android中的一些简单的adb命令

    外设为手机.也配置好了Android的adb环境变量,就可以执行了.

  3. sourceinsight - imsoft.cnblogs

    显示空格的问题,options->document options->visible space 前面的对勾去掉就好了 sourceinsight中文显示乱码问题彻底解决办法:http:/ ...

  4. Linux系统nat模式联网——VM是12 系统是cantos7

    >点击还原默认设置,然后确定 >选择Vmnet8,VMnet信息自动选中NAT模式 记住子网IP和子网掩码 >点击NAT设置,记住网关IP >点击DHCP.记住IP范围 > ...

  5. (2)字符编码关系和转换(bytes类型)

    ASCII 占一个字节,只支持英文 GB2312 占2个字节,只支持6700+汉字 GBK 是GB2312的升级版,支持21000+汉字 Shift-JIS 日本字符编码 ks_c-5601-1987 ...

  6. LG1397 [NOI2013]矩阵游戏

    题意 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][ ...

  7. Dataframe 新增一列, apply 通用方法

    df['c'] = df.apply(lambda row: 1 if row['a'] < 0 and row['b'] > 0 else 0, axis=1) apply 是一个好方法 ...

  8. smarty中调用php内置函数

    http://blog.csdn.net/clevercode/article/details/50373633

  9. FastAdmin 插件刷新缓存出现 200 红色提示框解决 always_populate_raw_post_data

    使用 phpStudy 全新安装了 FastAdmin,PHP 版本是 5.6. 安装完成后在刷新插件缓存时出现红色 提示消息,但状态 为 200. 打开 F12 看,发现有以下信息. <br ...

  10. Socket-Vs-WebSocket-TestTool

    项目地址 :  https://github.com/kelin-xycs/Socket-Vs-WebSocket-TestTool Socket-Vs-WebSocket-TestTool 一个用 ...