我尝试用nodejs的http模块接收并保存一个txt文件,但保存后文件中带有一部分多余的http数据,可以将这部分多余数据过滤掉吗?这是原文件和保存后的文件,以及代码。
https://github.com/pillarjs/multiparty 用组件
或者参考下面的代码:
/**
Multipart Parser (Finite State Machine)
usage:
var multipart = require('./multipart.js');
var body = multipart.DemoData(); // raw body
var body = new Buffer(event['body-json'].toString(),'base64'); // AWS case
var boundary = multipart.getBoundary(event.params.header['content-type']);
var parts = multipart.Parse(body,boundary);
// each part is:
// { filename: 'A.txt', type: 'text/plain', data: <Buffer 41 41 41 41 42 42 42 42> }
author: Cristian Salazar (christiansalazarh@gmail.com) www.chileshift.cl
Twitter: @AmazonAwsChile
*/
exports.Parse = function(multipartBodyBuffer,boundary){
var process = function(part){
// will transform this object:
// { header: 'Content-Disposition: form-data; name="uploads[]"; filename="A.txt"',
// info: 'Content-Type: text/plain',
// part: 'AAAABBBB' }
// into this one:
// { filename: 'A.txt', type: 'text/plain', data: <Buffer 41 41 41 41 42 42 42 42> }
var obj = function(str){
var k = str.split('=');
var a = k[0].trim();
var b = JSON.parse(k[1].trim());
var o = {};
Object.defineProperty( o , a ,
{ value: b, writable: true, enumerable: true, configurable: true })
return o;
}
var header = part.header.split(';');
var file = obj(header[2]);
var contentType = part.info.split(':')[1].trim();
Object.defineProperty( file , 'type' ,
{ value: contentType, writable: true, enumerable: true, configurable: true })
Object.defineProperty( file , 'data' ,
{ value: new Buffer(part.part), writable: true, enumerable: true, configurable: true })
return file;
}
var prev = null;
var lastline='';
var header = '';
var info = ''; var state=0; var buffer=[];
var allParts = [];
for(i=0;i<multipartBodyBuffer.length;i++){
var oneByte = multipartBodyBuffer[i];
var prevByte = i > 0 ? multipartBodyBuffer[i-1] : null;
var newLineDetected = ((oneByte == 0x0a) && (prevByte == 0x0d)) ? true : false;
var newLineChar = ((oneByte == 0x0a) || (oneByte == 0x0d)) ? true : false;
if(!newLineChar)
lastline += String.fromCharCode(oneByte);
if((0 == state) && newLineDetected){
if(("--"+boundary) == lastline){
state=1;
}
lastline='';
}else
if((1 == state) && newLineDetected){
header = lastline;
state=2;
lastline='';
}else
if((2 == state) && newLineDetected){
info = lastline;
state=3;
lastline='';
}else
if((3 == state) && newLineDetected){
state=4;
buffer=[];
lastline='';
}else
if(4 == state){
if(lastline.length > (boundary.length+4)) lastline=''; // mem save
if(((("--"+boundary) == lastline))){
var j = buffer.length - lastline.length;
var part = buffer.slice(0,j-1);
var p = { header : header , info : info , part : part };
allParts.push(process(p));
buffer = []; lastline=''; state=5; header=''; info='';
}else{
buffer.push(oneByte);
}
if(newLineDetected) lastline='';
}else
if(5==state){
if(newLineDetected)
state=1;
}
}
return allParts;
};
// read the boundary from the content-type header sent by the http client
// this value may be similar to:
// 'multipart/form-data; boundary=----WebKitFormBoundaryvm5A9tzU1ONaGP5B',
exports.getBoundary = function(header){
var items = header.split(';');
if(items)
for(i=0;i<items.length;i++){
var item = (new String(items[i])).trim();
if(item.indexOf('boundary') >= 0){
var k = item.split('=');
return (new String(k[1])).trim();
}
}
return "";
}
exports.DemoData = function(){
body = "trash1\r\n"
body += "------WebKitFormBoundaryvef1fLxmoUdYZWXp\r\n";
body += "Content-Disposition: form-data; name=\"uploads[]\"; filename=\"A.txt\"\r\n";
body += "Content-Type: text/plain\r\n",
body += "\r\n\r\n";
body += "@11X";
body += "111Y\r\n";
body += "111Z\rCCCC\nCCCC\r\nCCCCC@\r\n\r\n";
body += "------WebKitFormBoundaryvef1fLxmoUdYZWXp\r\n";
body += "Content-Disposition: form-data; name=\"uploads[]\"; filename=\"B.txt\"\r\n";
body += "Content-Type: text/plain\r\n",
body += "\r\n\r\n";
body += "@22X";
body += "222Y\r\n";
body += "222Z\r222W\n2220\r\n666@\r\n";
body += "------WebKitFormBoundaryvef1fLxmoUdYZWXp--\r\n";
return (new Buffer(body,'utf-8'));
// returns a Buffered payload, so the it will be treated as a binary content.
};
async function upload(event) {
let results = [];
let boundary = multipart.getBoundary(event.headers['content-type']);
console.log(`exec upload boundary ${boundary}, ${JSON.stringify(event.headers)}`);
let body = new Buffer(event.body, 'base64');
let files = multipart.Parse(body, boundary);
for (let index = 0; index < files.length; index++) {
const element = files[index];
let path = await saveFile(element.filename, element.data);
results.push(path);
}
return results;
}
强啊
debug调试下哪里多出来了这些东西。去掉
去不掉就重新过滤一遍,只把提取的密码输入进文件
我在尝试分片保存这些数据体,这些多余出来数据不太好和原始数据区分开来
你用http模块启动了一个服务器?
是的是的
@Naxis: 别用原生的了,如果你用的功能比较简单,可以用express,启动一个express服务器(其实还是对http模块的封装吧),这样至少路由什么的没那么麻烦了。如果需要提供很多服务,可以用更复杂一点的,koa,eggjs等等。。。
@顾晓北: 原生的确实是比较麻烦,不过现在公司的框架就是基于原生的nodejs
@Naxis: 什么叫【原生node】?node就是要引用其他包的啊?难不成你们是要自己开发一个什么包,要求是其他什么包都不依赖?
@顾晓北: 我们公司的框架都是部门里的大佬写的,基本不用外部框架的
@Naxis: 牛批,那你自己看吧,没用过http模块搞这个,不过应该不难。话说,难道你们公司是写框架的?写出框架给别人用?如果是做产品的,没什么意义啊
@顾晓北: 我们主管不喜欢用别人的框架,基本都是自己写的,所以不用express这种外部框架,连nodejs都是比较低的6.9版本的
@Naxis: 这是秀技术呢还是做产品呢?