zoukankan      html  css  js  c++  java
  • nodejs 模拟form表单上传文件

    使用nodejs来模拟form表单进行文件上传,可以同时上传多个文件。

    以前项目里有这个方法,最近在客户那里出问题了,同事说,这个方法从来就没管用过,SO,用了一天时间把这个方法给搞出来了(觉得花费的时间长了点),分享之。

    代码及测试用例:

    var http = require('http');
    var path = require('path');
    var fs = require('fs');
    
    function postFile(fileDataInfo, fileKeyValue, req) {
        var boundaryKey = Math.random().toString(16);
        var enddata = '
    ----' + boundaryKey + '--';
    
        var dataLength = 0;
        var dataArr = new Array();
        for (var i = 0; i < fileDataInfo.length; i++) {
            var dataInfo = "
    ----" + boundaryKey + "
    " + "Content-Disposition: form-data; name="" + fileDataInfo[i].urlKey + ""
    
    " + fileDataInfo[i].urlValue;
            var dataBinary = new Buffer(dataInfo, "utf-8");
            dataLength += dataBinary.length;
            dataArr.push({
                dataInfo: dataInfo
            });
        }
    
        var files = new Array();
        for (var i = 0; i < fileKeyValue.length; i++) {
            var content = "
    ----" + boundaryKey + "
    " + "Content-Type: application/octet-stream
    " + "Content-Disposition: form-data; name="" + fileKeyValue[i].urlKey + ""; filename="" + path.basename(fileKeyValue[i].urlValue) + ""
    " + "Content-Transfer-Encoding: binary
    
    ";
            var contentBinary = new Buffer(content, 'utf-8'); //当编码为ascii时,中文会乱码。
            files.push({
                contentBinary: contentBinary,
                filePath: fileKeyValue[i].urlValue
            });
        }
        var contentLength = 0;
        for (var i = 0; i < files.length; i++) {
            var filePath = files[i].filePath;
            if (fs.existsSync(filePath)) {
                var stat = fs.statSync(filePath);
                contentLength += stat.size;
            } else {
                contentLength += new Buffer("
    ", 'utf-8').length;
            }
            contentLength += files[i].contentBinary.length;
        }
    
        req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey);
        req.setHeader('Content-Length', dataLength + contentLength + Buffer.byteLength(enddata));
    
        // 将参数发出
        for (var i = 0; i < dataArr.length; i++) {
            req.write(dataArr[i].dataInfo)
            //req.write('
    ')
        }
    
        var fileindex = 0;
        var doOneFile = function() {
            req.write(files[fileindex].contentBinary);
            var currentFilePath = files[fileindex].filePath;
            if (fs.existsSync(currentFilePath)) {
                var fileStream = fs.createReadStream(currentFilePath, {bufferSize: 4 * 1024});
                fileStream.pipe(req, {end: false});
                fileStream.on('end', function() {
                    fileindex++;
                    if (fileindex == files.length) {
                        req.end(enddata);
                    } else {
                        doOneFile();
                    }
                });
            } else {
                req.write("
    ");
                fileindex++;
                if (fileindex == files.length) {
                    req.end(enddata);
                } else {
                    doOneFile();
                }
            }
        };
        if (fileindex == files.length) {
            req.end(enddata);
        } else {
            doOneFile();
        }
    }
    
    //测试用例
    //http://nodejs.org/api/http.html#http_http_request_options_callback
    var fileDataInfo = [
    	{urlKey: "abc", urlValue: "空格  中文"},
    	{urlKey: "def", urlValue: "asdfasfs123477"}
    ]
    
    var files = [
    	{urlKey: "file1", urlValue: "E:\1.jpg"},
    	{urlKey: "file2", urlValue: "文件不存在"},
    	{urlKey: "file3", urlValue: ""},
    	{urlKey: "file4", urlValue: ""},
    	{urlKey: "file5", urlValue: "E:\Pro 中文  空格.mp3"},
    	{urlKey: "file6", urlValue: "E:\DFBF.jpg"},
    	{urlKey: "file7", urlValue: ""}
    ]
    
    var options = {
        host: "localhost",
        port: "8908",
        method: "POST",
        path: "/Home/Upload"
    }
    
    var req = http.request(options, function(res) {
        console.log("RES:" + res);
        console.log('STATUS: ' + res.statusCode);
        console.log('HEADERS: ' + JSON.stringify(res.headers));
        //res.setEncoding("utf8");
        res.on("data", function(chunk) {
            console.log("BODY:" + chunk);
        })
    })
    
    req.on('error', function(e) {
        console.log('problem with request:' + e.message);
        console.log(e);
    });
    postFile(fileDataInfo, files, req);
    console.log("done");
    

    服务端测试,用mvc在home控制器写了个upload方法,并遍历上传的文件将其保存在硬盘上了。

    只是上传大文件会有问题,估计是需要服务器进行配置,暂且不管。

    服务端方法(写在了Home控制器下)

            [HttpPost]
            public string Upload()
            {
                foreach (string file in this.Request.Files)
                {
                    string strFileName = this.Request.Files[file].FileName;
                    if (string.IsNullOrEmpty(strFileName))
                        continue;
                    this.Request.Files[file].SaveAs(@"E:新建文件夹" + strFileName);
                }
                StringBuilder sb = new StringBuilder();
                foreach (string item in this.Request.Form.AllKeys)
                {
                    sb.AppendLine(string.Format("key:{0}  value:{1}", item, this.Request.Form[item]));
                }
                sb.AppendLine(@"保存成功 路径:E:新建文件夹");
                return sb.ToString();
            }
    

    运行脚本:

    node nodejsPostFile.js
    

    运行结果:

    示例下载

    nodejsPostFile4.rar

  • 相关阅读:
    参考vue.js实现双向绑定的方法理解双向绑定原理(:Object.defineProperty和发布-订阅模式)
    不错的站点 博文
    使用C#动态生成Word文档/Excel文档的程序测试通过后,部署到IIS服务器上,不能正常使用的问题解决方案
    详解HTML<head> 头标签元素的意义以及使用场景
    css奇特用法之 IMG添加背景图片配合显示--效果惊艳
    .net面试题-15k+左右
    微信小程序IOS真机调试发生了SSL 错误,无法建立与该服务器的安全连接
    微信小程序自定义组件-下拉框
    微信小程序语音(A)发给别人(B),也能播放,是需要先把语音上传到自己的服务器上才可以
    微信小程序循环中点击一个元素,其他的元素不发生变化,类似点击一个循环中的语音,其他的不发生点击事件
  • 原文地址:https://www.cnblogs.com/grj1046/p/3830918.html
Copyright © 2011-2022 走看看