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 = '\r\n----' + boundaryKey + '--';

    var dataLength = 0;
    var dataArr = new Array();
    for (var i = 0; i < fileDataInfo.length; i++) {
        var dataInfo = "\r\n----" + boundaryKey + "\r\n" + "Content-Disposition: form-data; name=\"" + fileDataInfo[i].urlKey + "\"\r\n\r\n" + 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 = "\r\n----" + boundaryKey + "\r\n" + "Content-Type: application/octet-stream\r\n" + "Content-Disposition: form-data; name=\"" + fileKeyValue[i].urlKey + "\"; filename=\"" + path.basename(fileKeyValue[i].urlValue) + "\"\r\n" + "Content-Transfer-Encoding: binary\r\n\r\n";
        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("\r\n", '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('\r\n')
    }

    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("\r\n");
            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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM