向服务器请求解析文件,post请求文件上传,服务器端的解析操作

有文件上传的操作时,nodeji服务器端接收的数据是下面的形式

------WebKitFormBoundaryyqmDhoteSLnZTpwj

Content-Disposition: form-data; name="user"

哈哈

------WebKitFormBoundaryyqmDhoteSLnZTpwj

Content-Disposition: form-data; name="f1"; filename="1.txt.txt"

Content-Type: text/plain

sdsadsdafdfdf

dsfdf

dfdf

dfedf

------WebKitFormBoundaryyqmDhoteSLnZTpwj--

对数据进行一定方式的整理如下:

\r\n

Content-Disposition: form-data; name="user"\r\n

\r\n

哈哈\r\n

\r\n

Content-Disposition: form-data; name="f1"; filename="1.txt.txt"\r\n

Content-Type: text/plain\r\n

\r\n

sdsadsdafdfdf

dsfdf

dfdf

dfedf\r\n

进一步再进行相关处理如下:

\r\n[数据描述]\r\n\r\n[数据值]\r\n

\r\n[数据描述1]\r\n[数据描述2]\r\n\r\n[数据内容]\r\n

以上表示最终得到的处理结果,普通的表单数据数据描述只有一个,而对于文件上传的有两个,而相关的数据内容都存在于分隔符之间获取到的第一个\r\n\r\n中间

相关的解析步骤如下:

用分隔符将数据切开

[

空,

\r\n数据描述\r\n\r\n数据值\r\n,

\r\n数据描述1\r\n数据描述2\r\n\r\n\r\n,

--\r\n

]

丢弃头尾的元素

[

\r\n数据描述\r\n\r\n数据值\r\n,

\r\n数据描述1\r\n数据描述2\r\n\r\n\r\n,

]

丢弃每一项中的\r\n

[

数据描述\r\n\r\n数据值,

数据描述1\r\n数据描述2\r\n\r\n,

]

用第一次出现的"\r\n\r\n"切分数据

普通数据可以切分为[数据描述][数据值] 或

文件数据可以切分为[数据描述1]\r\n[数据描述2][文件内容]

判断描述的里面有没有"\r\n"

有——文件数据:[数据描述1\r\n数据描述2, ]

没有——普通数据:[数据描述, 数据值]

分析"数据描述"

具体的代码实现如下:

const http = require("http");

const querystring = require("querystring");

const fs = require("fs");

const uuid = require("uuid/v4");

Buffer.prototype.split = Buffer.prototype.split || function(b){

let arr = [];

let cur = 0;

let n = 0;

while( ( n = this.indexOf(b,cur) ) != -1 ){

arr.push(this.slice(cur,n));

cur = n+b.length;

}

arr.push(this.slice(cur));

return arr;

}

let server = http.createServer((req,res)=>{

let arr = [];

req.on("data",(data)=>{

arr.push(data);

})

req.on("end",()=>{

//拼接二进制数据

let data = Buffer.concat(arr);

let post = {};

let files = {};

//对二进制数据的出处理方式

//通过请求头里面的content-type获取boundary

if(req.headers["content-type"]){

//获取分界线boundary

let str = req.headers["content-type"].split("; ")[1];

if(str){

let boundary = "--"+str.split("=")[1];

//1. 用分割线切开数据

let arr = data.split(boundary);

//2. 丢弃头尾的数据

arr.shift();

arr.pop();

//3. 丢弃每一项中的\r\n

arr = arr.map(buffer=>buffer.slice(2,buffer.length-2));

//用第一次出现的\r\n\r\n切分数据

arr.forEach(buffer=>{

let n = buffer.indexOf("\r\n\r\n");

let disposition = buffer.slice(0,n);

let content = buffer.slice(n+4);

disposition = disposition.toString();

//用描述信息里面是否存在"\r\n"区分普通数据和文件数据

if(disposition.indexOf("\r\n")==-1){

//普通数据

content = content.toString();

let name = disposition.split("; ")[1].split("=")[1];

name = name.substring(1,name.length-1);

post[name] = content;

console.log("普通数据",post);

}else{

// 文件数据

let [line1,line2] = disposition.split("\r\n");

let [,name,filename] = line1.split("; ");

let type = line2.split("; ")[1];

name = name.split("=")[1];

name = name.substring(1,name.length-1);

filename = filename.split("=")[1];

filename = filename.substring(1, filename.length - 1);

let path = `upload/${uuid().replace(/\-/g,"")}`;

console.log("写入的文件路径是:",path);

fs.writeFile(path,content,(err)=>{

if(err){

console.log("写入文件失败了",err);

}else{

files[name] = {filename, path, type};

console.log("写入成功",files);

}

})

}

})

}

}

res.end();

})

});

server.listen(8080);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值