NodeJS图片上传或文件上传(非express框架)

NodeJS的图片或文件上传,如果使用express框架实现起来非常简单,但是,对于那些已经使用非express框架创建集群的应用场景,混用express框架会带来诸多问题,还是要基于现有技术解决。这其中的重点就在于如何识别各个参数,并将文件流数据分离出来,下面先来看看上传数据的格式:

[回车]
Content-Disposition: form-data; name="text"[回车]
[回车]
[回车]
------WebKitFormBoundaryXXXXXXX[回车]
Content-Disposition: form-data; name="avatar"; filename="111.jpg"[回车]
Content-Type: image/jpeg[回车]
文件流数据[回车]
------WebKitFormBoundaryXXXXXX[回车]

 第一步,将传入的数据变成二进制数组

第二步,根据\r\n分离数据和报头

第三步,根据上传数据的格式,并获得参数名称,参数值,以及其他属性。上传数据格式中以“------WebKitFormBoundary”开头的字符串是各参数信息的分隔符,每个参数至少有三组数据,Content-Disposition,Content-Type以及参数值。

第四步,将文件或图片数据保存到本地,并将文件URI返回给Client

// 上传文件函数
var upload = function(request, response){
    var chunks = [];
    var size = 0;
    request.on('data' , function(chunk){
        chunks.push(chunk);
        size+=chunk.length;
    });

    request.on("end",function(){
        var buffer = Buffer.concat(chunks , size);
        if(!size){
            response.writeHead(404);
            response.end('');
            return;
        }

        var rems = [];

        //根据\r\n分离数据和报头
        for(var i=0;i<buffer.length;i++){
            var v = buffer[i];
            var v2 = buffer[i+1];
            if(v==13 && v2==10){
                rems.push(i);
                log(i);
            }
        }
        
        var params = new Map();
        for ( var i = 0 ; i < rems.length-1 ; i++ ) {    
            // 从数据流中取出每一个被\r\n分离的数据,并进行处理
            var line = buffer.slice(rems[i]+2,rems[i+1]).toString();
            if ( line.startWith("------WebKitFormBoundary") ) {
                continue;
            } else if ( line.startWith("Content-Disposition: form-data;") )  {
                var parts = line.split(";");
                // 获得param的name
                var name = parts[1].trim().split("=")[1].replace(/\"/g,""); 
                //如果参数存在文件名,获得文件名
                var fileName;
                if ( parts.length > 2 ){
                    fileName = parts[2].trim().split("=")[1].replace(/\"/g,"");
                }  
                    
                //log(">>> name = " + name + " >>>> filename = " + fileName);
                i++;
                var type = buffer.slice(rems[i]+2,rems[i+1]).toString();
                type = type.substr("Content-Type:".length).trim();
                //log(">>> type = " + type);
                if ( type != undefined ){
                    i++;
                    if ( type == "image/jpeg" ){
                        if ( fileName != undefined ) {
                            var imgObject = new Object();
                            imgObject.type = "img";
                            imgObject.data = buffer.slice(rems[i]+4,rems[rems.length-2]);
                            imgObject.path = './upload/'+fileName;
                            imgObject.size = rems[rems.length-2] - (rems[i]+2);
                            params.set("upload_file",imgObject);
                            log("图片路径:" + imgObject.path + ";图片大小:"+imgObject.size);
                        } else {
                            // 将请求中的图片设置为空
                            log("上传图片为空");
                            params.set(name,undefined);
                        }                        
                    } else {
                        var value = buffer.slice(rems[i]+2,rems[i+1]).toString();
                        // 将请求中的参数提取出来
                        params.set(name,value);
                        log("参数名称:"+name + " ;参数值:"+value );
                    }                            
                        
                } 
            } 
        } 
        
        // 保存文件
        var fileObj = params.get("upload_file");
        fs.writeFileSync(fileObj.path, fileObj.data);
                
        var obj = new Object();
        obj.fileId = uuid.v1();
        obj.filePath = fileObj.path;
        obj.createdTime = new Date();
                
        response.end(JSON.parse(obj));
        
        });
    });
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值