Node.js实现文件上传

在工作中碰到了这样的需求,需要用nodejs 来上传文件,之前也只是知道怎么通过浏览器来上传文件, 用nodejs的话, 相当于模拟浏览器的行为。 google 了一番之后, 明白了浏览器无非就是利用http协议来给服务器传输数据, 具体协议就是《RFC 1867 - Form-based File Upload in HTML》, 在浏览器上通过form 表单来上传文件就是通过这个协议,我们可以先看看浏览器给服务端发送了什么数据, 就可以依葫芦画瓢的把上传功能实现出来。说起form 表单上传文件的话, 大家应该很熟悉:

rush:js;">


提交时, 用fiddler 抓包可以看到向服务端发出这样的数据:

POST http://www.qq.com/ HTTP/1.1 Host: www.qq.com Content-Length: 23 Content-Type: application/x-www-form-urlencoded; charset=UTF-8

text1=hello&text2=world

值得注意的是Content-Type认为application/x-www-form-urlencoded,所以消息会经过URL编码。比如“你好”会编码为 %E4%BD%A0%E5%A5%BD。

接下来我们看一下通过form 表单是怎么上传的。大家应该也不陌生:

rush:js;">

然后新建一个只有hello world字样的upload.txt文本文件上传上去,我们再吃用fiddler 来抓下包, 可以发现发送过去的数据稍微复杂了一些(已经去掉了很多的其它没关系的请求行,比如缓存控制和cookie之类的):

POST http://www.qq.com/ HTTP/1.1 Host: www.qq.com Content-Length: 199 Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywr3X7sXBYQQ4ZF5G

------WebKitFormBoundarywr3X7sXBYQQ4ZF5G Content-disposition: form-data; name="myfile"; filename="upload.txt" Content-Type: text/plain

hello world

------WebKitFormBoundarywr3X7sXBYQQ4ZF5G--

根据RFC 1867的定义,我们需要生成一段边界数据,这个数据不能在内容的其它地方出现,这个可以自己定义, 在每个浏览器的生成算法可能都不一样, 上面的boundary就是分隔数据,生成了分隔数据之后, 就可以把分隔数据放在头部的Content-Type里面传送给服务端, 也就是上文的 Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywr3X7sXBYQQ4ZF5G, 另外,上传内容,需要用分隔数据来分隔成若干个段,然后每段数据里面都有文件文件名,还有上传时候的name,服务端就是用这个name来接收文件,还有文件的类型Content-Type,在这个例子里是 text/plain,如果上传的是png图片就是image/png。文件类型的一个空行后就是所上传文件内容在这个例子里也是为了容易理解所以上传的是文本文件所以内容直接就能够显示出来,如果上传的是图片文件, 因为是二进制文件fiddler 就显示的是乱码。 文件内容结束之后就是一个空行再加上边界数据。

了解了发送格式的细节之后, 下一步就是使用nodejs来编程实现,简单来讲, 就是按照格式把数据发送给服务端就行了。

rush:js;"> const http = require('http'); const fs = require('fs'); //post地址为本地服务的一个PHP,用于测试上传是否成功 var options = { hostname: 'localhost',port: 80,path: '/get.PHP',method: 'POST' } //生成分隔数据 var boundaryKey = '----WebKitFormBoundaryjLVkbqXtIi0YGpaB'; //读取需要上传文件内容 fs.readFile('./upload.txt',function (err,data) { //拼装分隔数据段 var payload = '--' + boundaryKey + '\r\n' + 'Content-disposition:form-data; name="myfile"; filename="upload.txt"\r\n' + 'Content-Type:text/plain\r\n\r\n'; payload += data; payload += '\r\n--' + boundaryKey + '--'; //发送请求 var req = http.request(options,function (res) { res.setEncoding('utf8'); res.on('data',function (chunk) { console.log('body:' + chunk); }); }); req.on('error',function(e) { console.error("error:"+e); }); //把boundary、要发送的数据大小以及数据本身写进请求 req.setHeader('Content-Type','multipart/form-data; boundary='+boundaryKey+''); req.setHeader('Content-Length',Buffer.byteLength(payload,'utf8')); req.write(payload); req.end(); });

本文重点在于了解协议并且用代码实现出来, 代码组织上面还有很多优化的地方。

最后在本地apache,简单写一个PHP来保存上传文件来用作测试:

rush:PHP;">

另外,根据RFC 1867 还可以实现一次上传多个文件功能, 这个在这里就不详述, 需要的话可以详细参考RFC 1867来实现。

以上所述是小编给大家介绍的Node.js实现文件上传。编程之家 jb51.cc 收集整理的教程希望能对你有所帮助,如果觉得编程之家不错,可分享给好友!感谢支持

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...