使用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

nodejs 模拟form表单上传文件的更多相关文章

  1. django 基于form表单上传文件和基于ajax上传文件

    一.基于form表单上传文件 1.html里是有一个input type="file" 和 ‘submit’的标签 2.vies.py def fileupload(request ...

  2. 巨蟒python全栈开发django11:ajax&&form表单上传文件contentType

    回顾: 什么是异步? 可以开出一个线程,我发出请求,不用等待返回,可以做其他事情. 什么是同步? 同步就是,我发送出了一个请求,需要等待返回给我信息,我才可以操作其他事情. 局部刷新是什么? 通过jq ...

  3. vue form表单上传文件

    <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js">< ...

  4. 使用form表单上传文件

    在使用form表单上传文件时候,input[type='file']是必然会用的,其中有一些小坑需要避免. 1.form的 enctype="multipart/form-data" ...

  5. JsonResponse类的使用、form表单上传文件补充、CBV和FBV、HTML的模板语法之传值与过滤器

    昨日内容回顾 Django请求生命周期 # 1.浏览器发起请求 到达Django的socket服务端(web服务网关接口) 01 wsgiref 02 uwsgi + nginx 03 WSGI协议 ...

  6. PHP CURL 模拟form表单上传遇到的小坑

    1:引用的时候 $parans ['img']=new \CURLFile($param); 传入的文件 在PHP版本5.5以上记得new CURLFile 不然会上传不成功 /** * http p ...

  7. PHP 后台程序配置config文件,及form表单上传文件

    一,配置config文件 1获取config.php文件数组, 2获取form 表单提交的值 3保存更新config.php文件,代码如下: $color=$_POST['color']; $back ...

  8. form表单上传文件使用multipart请求处理

    在开发Web应用程序时比较常见的功能之一,就是允许用户利用multipart请求将本地文件上传到服务器,而这正是Grails的坚固基石——spring MVC其中的一个优势.Spring通过对Serv ...

  9. 通过form表单上传文件获取后台传来的数据

    小伙伴是不是遇到过这样的问题,通过submit提交form表单的时候,不知怎么获取后台传来的返回值.有的小伙伴就会说你不会发送ajax,其实也会.假如提交的form表单中含有文件,怎么办? 步骤1:想 ...

随机推荐

  1. WPF点滴

    1 设置窗体的最大化,而且无边框 <Style x:Key="WindowsStyle" TargetType="Window"> <Sett ...

  2. 3 分钟的高速体验 Apache Spark SQL

    "War of the Hadoop SQL engines. And the winner is -?" 这是一个非常好的问题.只要.无论答案是什么.我们都值花一点时间找出 Sp ...

  3. CENTOS安装部署zabbix

    果学网 -专注IT在线www.prismcollege.com 參考原文:http://www.showerlee.com/archives/13 RHCE过的EMAIL已经下来.所以近期闲了就准备把 ...

  4. poj1185炮兵阵地

    #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> ...

  5. javascript - 浏览TOM大叔博客的学习笔记

    part1 ---------------------------------------------------------------------------------------------- ...

  6. C# 如何获取某用户的“我的文档”的目录

    Console.WriteLine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); System.E ...

  7. Perl中的单行凝视和多行凝视

    同其它大多数编程语言一样.Perl中的单行凝视也是#开头.比如: #print "Hello,World!"; 但多行凝视.不同的语言有不同的凝视方式,比方说: Java,C/C+ ...

  8. c# ThreadPoold使用心得

    于c#多线程编程经常使用的线程,但是,因为线程的创建和销毁是非常资源 - 成本非常大.因此,我们使用线程池来解决问题, 在线程池的开始是申请一定数量的线程系统.和维护,有任务时间,假设你有空闲的线程, ...

  9. 9种CSS3 blend模式制作的鼠标滑过图片标题特效

    这是一款使用CSS3 background-blend-mode制作的鼠标滑过图片标题特效.该图片标题特效在鼠标滑过一张图片的时候,图片的标题会对应的动画,而且图片会使用css blend模式渲染为很 ...

  10. WF系列——工作流基本知识

    工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现某个预期的业务目标 ...