由于公司开发需求,在web端和java服务端需要加一层nodejs业务服务。用nodejs封装java接口。对于一般同步接口,nodejs和java之间只是业务接口api的调用,封装起来比较容易,但是对于数据流,异步的封装来说可能有些东西需要注意的了,我这篇主要想说一下我在处理学习需求要求的过程和想法。
业务需求:
转发用户提交的文件数据及字符串数据。
1:拿到这个需求之后我第一想法是拿到用户的缓存然后做解析处理(我之前对http请求的具体过程并不了解,我的想法只是基于一般的理解)。
但是实际情况是multipart/form-data类型的http请求是包括两两部分,一部分是headers头信息部分,一部分是data数据部分,headers包含了data部分解析的分隔符。这部分信息在请求的同时就发送过来了,是同步的。不需要我们做解析。data数据是异步的需要监听获取,我一开始以为这两部分是揉在一起的。浪费了很多时间。
2:由于一开始并不理解nodejs是如何接收,然后如何在发送的。我就baidu搜索了一个nodejs保存上传文件的插件(formidable),看了一下插件里的写法,知道了通过请求对象req来获取用户请求的数据流的方法 req.on('data', function (buffer) { });然后想通过分析formidable执行原理,然后修改代码实现业务需求,结果做了很多断点之后发现几个问题
1:缓存问题
formidable是把接收到的数据写入临时文件中,如果想把所有数据写入buffer缓存,不太容易确定buffer的大小,buffer要在创建的时候指定大小,而且太大的文件不利于全部写入buffer。
2:使用临时文件处理
如果要用临时文件处理要考虑拼装数据流,要把文件名,分隔符,回车换行等信息重新拼装成数据流发送,而且还要计算数据库长度写在发送的headers里。
3:折中办法
修改了一下需求,让web分开发送字符串数据和文件数据,文件数据我这里接收后直接转发,这样我只需要在nodejs中发起对java服务器接口的http请求然后把接收到的数据修改下headers直接发送就可以。这样免去了buffer长度计算问题和拼接数据流等问题
4:调试流
调试这种数据流格式问题其实可以用一个最小的数据流,小文件做测试然后在后端直接转义打印一下,这样比调试别人的插件可能来的跟简单
var form = new FormData();
encoding = 'utf8';
let object = {};
object.method = 'POST';
object.port = 80;
object.host = 'xxxx.com';
object.path = '/xxxxxx';
object.headers = {};
if (req.headers['accept']) {
object.headers['accept'] = req.headers['accept']
}
if (req.headers['accept-encoding']) {
object.headers['accept-encoding'] = req.headers['accept-encoding']
}
if (req.headers['connection']) {
object.headers['connection'] = req.headers['connection']
}
if (req.headers['content-length']) {
object.headers['content-length'] = req.headers['content-length']
}
if (req.headers['content-type']) {
object.headers['content-type'] = req.headers['content-type']
}
object.headers['Authorization'] = global.serverTocken;
let data = '';
let nodeReq = http.request(object, function (res) {
var gzip = zlib.createGunzip();
res.pipe(gzip);
output = gzip;
output.on('data', function (chunk) {
data += chunk.toString('utf-8');
});
output.on('end', function () {
self.send(data);
});
});
req
.on('error', function (err) {
nodeReq.abort();
nodeReq.end();
})
.on('aborted', function () {
nodeReq.abort();
nodeReq.end();
})
.on('data', function (buffer) {
nodeReq.write(buffer);
})
.on('end', function () {
nodeReq.end();
});
zlib:是处理返回乱码问题
网友评论