node通过http.request向其他服务器上传文件
发布于 3年前 作者 seon 3444 次浏览

很早就听说过node的大名了,只是一直没有去尝试。直到最近,为了简化代码上线流程,提高上线效率,决定使用node来开发服务器端的上线程序。

服务器主要完成在svn服务器上创建tag,代码的合并、压缩与打包,压缩包提交至CMS服务器,经由CMS服务器发布至全网cdn等一系列的流程。

开始的一系列开发工作都比较顺利,但是,当做到将压缩包上传至CMS服务器时,遇到了困难。我不知道该如何通过node发起一条带有文件的post请求。。。

通过查阅node的api手册,发现node是支持在服务器端发起http请求的。那么,剩下的麻烦的问题,就是,该如何构造该请求。

之前虽然也写过一段时间的后端代码,但是都是通过封装好的接口来实现的,但对于node来说,没有现成的实现。无奈,只好向google求助。

很快搜到了一篇帖子,介绍相关内容的,并且还附赠了代码!不过可惜的是,所附的代码还是存在问题,估计作者并没有亲测过。但这篇帖子却着实的让我受到了很大的启发,至少让我清楚了两件事情:1、上传文件的http请求的body部分的格式;2、文件转化为http数据流的方式!

基于以上两点,我慢慢摸索出了上传文件的方法,在这里跟大家分享以下!

先简单的描述下http协议分包传输时的数据格式。

Content-type

Content-type需要指定为

multipart/form-data; boundary=’ + boundaryKey

其中boundaryKey为一随机字符串,用于标识请求数据段。

请求体格式

每一段请求体均以"–" + boundaryKey开头,然后使用’\r\n’来做行分隔。

接下来是每一段请求体的描述信息,包括Content-Type以及
Content-Disposition
等字段信息。每一个字段信息结尾都以’\r\n’来标识行结束。

描述信息与请求体正文需要以一个空行隔开,即需要再输出一个’\r\n’。

最后是请求提正文。

直到最后一个请求体结束之后,再输出’\r\n–’ + boundaryKey + '–’作为整个请求的结束。

这样即完成了一次post请求所需的基本内容了。

接下来,在介绍下,将文件转换为http数据流所需要做的工作。

转换的基本过程:

  1. 调用http.request方法,返回一个
    http.ClientRequest类的实例
    http.ClientRequest的实例本质上来说是一个
    writable stream。

  2. 对要上传的文件创建一个读取文件流。

  3. 将从文件读取到的流数据写到http请求数据流中。

  4. 关闭http请求。


所需要用到的接口:

  1. http.request

  2. createReadStream

  3. stream.pipe

  4. stream.on(‘end’)事件


综合以上内容,给出简单实现的代码,供大家参考,欢迎大家交流!
function upload(){

var boundaryKey = '----' + new Date().getTime();
var options = {
host:’www.test.com’,//远端服务器域名
port:80,//远端服务器端口号
method:’POST’,
path:’/upload’,//上传服务路径
headers:{
‘Content-Type’:’multipart/form-data; boundary=’ + boundaryKey,
‘Connection’:’keep-alive’
}
};
var req = http.request(options,function(res){
res.setEncoding(‘utf8’);
res.on('data’, function (chunk) {
console.log('body: ' + chunk);
});
res.on('end’,function(){
console.log(‘res end.’);
});
});
req.write(
‘–’ + boundaryKey + ‘\r\n’ +
‘Content-Disposition: form-data; name="upload"; filename="test.zip"\r\n’ +
‘Content-Type: application/x-zip-compressed\r\n\r\n’
);
//设置1M的缓冲区
var fileStream = fs.createReadStream('/data/test.zip’,{bufferSize:1024 * 1024});
fileStream.pipe(req,{end:false});
fileStream.on('end’,function(){
req.end(‘\r\n–’ + boundaryKey + ‘–’);
});
}

1 回复

能说说服务器端是怎么接受的么

回到顶部