node 上传文件 http client to post file
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换行 不可缺少
代码实现
1 var http = require('http') 2 var fs = require('fs') 3 var querystring = require('querystring') 4 var path = require('path') 5 var util = require('util') 6 7 var boundaryKey = Math.random().toString(16); // random string 8 var reqdata = { 9 'abc' : '123' 10 } 11 12 var request = http.request({ 13 host : 'abc.com', 14 port : 80, 15 path : '/abc', 16 method : 'POST' 17 }, function (response) { 18 var data = ''; 19 response.on('data', function(chunk) { 20 data += chunk.toString(); 21 }); 22 response.on('end', function() { 23 console.log(data); 24 }); 25 }); 26 27 var enddata = '\r\n--' + boundaryKey + '--'; 28 function mkfield (field, value) { 29 return util.format('Content-Disposition: form-data; name="%s"\r\n\r\n%s', field, value); 30 } 31 var payload = '--' + boundaryKey + '\r\n' 32 for (var name in reqdata){ 33 payload += mkfield(name ,reqdata[name]) + util.format('\r\n--%s\r\n', boundaryKey) 34 } 35 payload += 'Content-Disposition:form-data; name="img"; filename="image.jpg"\r\n' 36 + 'Content-Type:image/jpeg\r\n' 37 + 'Content-Transfer-Encoding: binary\r\n' 38 + '\r\n'; 39 40 request.setHeader('Content-Type', 'multipart/form-data; boundary='+boundaryKey+''); 41 //request.setHeader('Content-Length', Buffer.byteLength(payload)+Buffer.byteLength(enddata)) 42 43 request.write(payload ) 44 45 fs.createReadStream('文件路径', { bufferSize: 4 * 1024 }) 46 .on('end', function() { 47 //报文结束 48 request.end(enddata); 49 }).pipe(request, { end: false })