使用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. 一个简单而经典的RTX51 Tiny应用实例

    关于RTX51 Tiny嵌入式实时操作系统的描写叙述请參考本人的上一篇博文(RTX51 Tiny实时操作系统学习笔记-初识RTX51 Tiny). 本篇博文.我将通过一个实例代码,带大家深入了解一下R ...

  2. iOS很重要的 block回调

    刚刚进入ios开发行业,发现开发中要用到大量的block回调,由此可见它的重要性.学习它之前我也是网上找的资料,推荐这篇文章http://blog.csdn.net/mobanchengshuang/ ...

  3. 【Android】应用启动画面

    几乎所有的Android应用程序都会有一个启动画面,展示自己的LOGO,本版信息,或者更人性化一点的,在很长的加载信息中,变换一些显示的文字等,让无聊的等待时间添加点调味剂. 具体实现来说,应该创建一 ...

  4. windows phone 加速计(5)

    原文:windows phone 加速计(5) 在windows phone 中存在着加速计,我们可以利用加速计获得用户手机的状态,根据手机状态调整我们的程序,这样会更人性化:windows phon ...

  5. python学习笔记--for循环

    推荐一个学习语言的网站:http://www.codecademy.com 有教程,可以边学边写,蛮不错的. for循环: 1.for loops allow us to iterate throug ...

  6. J2EE请求和响应—Servlet

    一.什么是Servlet? Servlet是执行Webserver上的一个特殊Java类.其特殊用途是响应client请求并做出处理.使得client与server端进行交互. 二.生命周期  Ser ...

  7. HDU 3177 Crixalis&#39;s Equipment(贪婪)

    主题链接:http://acm.hdu.edu.cn/showproblem.php? pid=3177 Problem Description Crixalis - Sand King used t ...

  8. 广东省-IT红黑榜排名公司名称

    红榜Top100 Order Company Name Point Change  1 百富计算机技术(深圳)有限公司  94.00 --  2 中国网通广州分公司  88.00 --  3 深圳市汇 ...

  9. [Django](1093, &quot;You can&#39;t specify target table &#39;fee_details_invoices&#39; for update in FROM clause&quot;) 错误

    dele_id = Fee_details_invoices.objects.filter(fee_detail_id__in=fee_id_list, return_type='2').values ...

  10. VS2010不能编译SQLServer2005的Microsoft.SQLServer.ManagedDTS.dll的解决方法

    VS2010不能编译SQLServer2005的Microsoft.SQLServer.ManagedDTS.dll是最近碰到的一个疑难杂症问题,通过查询微软社区和一些英文资料找到了解决方法,同事说之 ...