美文网首页
post请求文件上传,服务器端的解析操作

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

作者: 天问ing | 来源:发表于2019-01-08 12:48 被阅读0次
    1. 有文件上传的操作时,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--
    
    1. 对数据进行一定方式的整理如下:
    <分隔符>\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
    <分隔符>
    
    1. 进一步再进行相关处理如下:
    <分隔符>\r\n[数据描述]\r\n\r\n[数据值]\r\n
    <分隔符>\r\n[数据描述1]\r\n[数据描述2]\r\n\r\n[数据内容]\r\n
    <分隔符>
    

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

    1. 相关的解析步骤如下:
      1. 用分隔符将数据切开
      [
          空,
          \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数据描述\r\n\r\n数据值\r\n,
          \r\n数据描述1\r\n数据描述2\r\n\r\n<文件内容>\r\n,
      ]
      
      1. 丢弃每一项中的\r\n
      [
          数据描述\r\n\r\n数据值,
          数据描述1\r\n数据描述2\r\n\r\n<文件内容>,
      ]
      
      1. 用第一次出现的"\r\n\r\n"切分数据
          普通数据可以切分为[数据描述][数据值] 或
          文件数据可以切分为[数据描述1]\r\n[数据描述2][文件内容]
      
      1. 判断描述的里面有没有"\r\n"
          有——文件数据:[数据描述1\r\n数据描述2, <文件内容>]
          没有——普通数据:[数据描述, 数据值]
      
      1. 分析"数据描述"

    具体的代码实现如下:

    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);
    

    相关文章

      网友评论

          本文标题:post请求文件上传,服务器端的解析操作

          本文链接:https://www.haomeiwen.com/subject/admmrqtx.html