node做http client 发送post数据是很容易的事情,但要上传文件就不是太容易了
主要是因为上传文件的报文和普通post是不太一样的
要了解http post可以看下这个 https://imququ.com/post/four-ways-to-post-data-in-http.html
npm上封装好的第三方库很多 比如request,我们来看下自己实现需要怎么做
首先要声称个随机串,这个是用来做分段的标记
var boundaryKey = Math.random().toString(16)
上传文件时要设置请求头 Content-Type : 'multipart/form-data; boundary='+boundaryKey+''
报文格式是这样的:
假如 boundaryKey=AaB03x
Content-Type: multipart/form-data; boundary=AaB03x --AaB03x
Content-Disposition: form-data; name="submit-name" Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain ... contents of file1.txt ...
--AaB03x--
from https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
每个字段用 “--”+分割符号 分段
结尾用 “--”+分割符号+“--” 注意用\r\n换行 不可缺少
代码实现
var http = require('http')
var fs = require('fs')
var querystring = require('querystring')
var path = require('path')
var util = require('util') var boundaryKey = Math.random().toString(); // random string
var reqdata = {
'abc' : ''
} var request = http.request({
host : 'abc.com',
port : ,
path : '/abc',
method : 'POST'
}, function (response) {
var data = '';
response.on('data', function(chunk) {
data += chunk.toString();
});
response.on('end', function() {
console.log(data);
});
}); var enddata = '\r\n--' + boundaryKey + '--';
function mkfield (field, value) {
return util.format('Content-Disposition: form-data; name="%s"\r\n\r\n%s', field, value);
}
var payload = '--' + boundaryKey + '\r\n'
for (var name in reqdata){
payload += mkfield(name ,reqdata[name]) + util.format('\r\n--%s\r\n', boundaryKey)
}
payload += 'Content-Disposition:form-data; name="img"; filename="image.jpg"\r\n'
+ 'Content-Type:image/jpeg\r\n'
+ 'Content-Transfer-Encoding: binary\r\n'
+ '\r\n'; request.setHeader('Content-Type', 'multipart/form-data; boundary='+boundaryKey+'');
//request.setHeader('Content-Length', Buffer.byteLength(payload)+Buffer.byteLength(enddata)) request.write(payload ) fs.createReadStream('文件路径', { bufferSize: * })
.on('end', function() {
//报文结束
request.end(enddata);
}).pipe(request, { end: false })