利用socket模拟http的混合表单上传(在一个请求中提交表单并上传多个文件)
在非常多企业级应用中,我们都没法直接通过开发语言sdk包封装的http工具来模拟http复合表单(multipart/form-data),特别是在跨语言跨平台的编程过程中。事实上实现方案并不复杂,仅仅要你了解了http协议中复合表单的报文结构就非常easy了:
httpheader
------时间戳------
表单參数1
------时间戳------
表单參数2
------时间戳------
文件1的描写叙述+二进制信息
------时间戳------
文件2的描写叙述+二进制信息
以下我们进一步以一段c#的代实例码来演示下这个结构:
///<summary>
///向server发送混合型的请求,1:成功发送,0:发送失败
///</summary>
///<param name="paranames">表单參数名数组</param>
///<param name="paravalues">參数值数组</param>
///<param name="files">文件名称数组</param>
///<param name="errmsg">报错信息</param>
///<returns></returns>
public
int SendRequest(string[] paranames,
string[] paravalues, string[] files,
ref string errmsg)
{
StringBuilder http, text;
byte[] httpbyte;
byte[] textbyte =
null;
long length = 0;
DateTime now =
DateTime.Now;
List<byte[]> data =newList<byte[]>();
//构造时间戳
string strBoundary =
"------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundary =
Encoding.ASCII.GetBytes("\r\n" + strBoundary +"\r\n");
length += boundary.Length;
//构造时间戳
//载入表单參数信息
if (paranames !=
null)
{
text = new
StringBuilder();
for (int i = 0; i < paranames.Length; i++)
{
text.Append("--");
text.Append(strBoundary);//加入时间戳
text.Append("\r\n");
text.Append("Content-Disposition: form-data; name=\"" + paranames[i] +"\"\r\n\r\n");
text.Append(paravalues[i]);
text.Append("\r\n");
}
string para = text.ToString();
textbyte = Encoding.ASCII.GetBytes(para);
length += textbyte.Length;
}
//载入文件信息
if (files !=
null)
{
for (int i = 0; i < files.Length; i++)
{
FileStream fs;
StringBuilder sbfile =newStringBuilder();
try
{
fs = File.Open(files[i],FileMode.Open,FileAccess.Read,FileShare.Read);
if (i == 0) sbfile.Append("--");//加入文件
else sbfile.Append("\r\n--");
sbfile.Append(strBoundary);//加入时间戳
sbfile.Append("\r\n");
sbfile.Append("Content-Disposition: form-data; name=\"");
sbfile.Append("file");
sbfile.Append("\"; filename=\"");
sbfile.Append(Path.GetFileName(files[i]));
sbfile.Append("\"");
sbfile.Append("\r\n");
sbfile.Append("Content-Type: ");
sbfile.Append("application/octet-stream");
sbfile.Append("\r\nContent-Length:");
sbfile.Append(fs.Length.ToString());
sbfile.Append("\r\n");
sbfile.Append("\r\n");
string temp = sbfile.ToString();
byte[] bin =Encoding.UTF8.GetBytes(temp);
data.Add(bin);
length += bin.Length;
length += fs.Length;
fs.Close();
}
catch (Exception exc)
{
errmsg = exc.Message.ToString();
return 0;
}
}
}
//构造http头
http = new
StringBuilder();
http.Append("POST " + ur.ToString() +" HTTP/1.1\r\n");
http.Append("Content-Type:multipart/form-data;boundary=");
http.Append(strBoundary);
http.Append("\r\n");
http.Append("Host:" + ipaddress +":" + tcpport.ToString() +"\r\n");
http.Append("Content-Length:");
http.Append(length.ToString());
http.Append("\r\n");
http.Append("Expect: 100-continue\r\n");//注明要在收到server的continue消息后才继续上传http消息体
http.Append("Connection: Keep-Alive\r\n\r\n");
string strtemp = http.ToString();
httpbyte = Encoding.ASCII.GetBytes(strtemp);
try
{
soc.Send(httpbyte);"//首先发送http头
Thread.Sleep(100);
string check = GetResponse();
if (check ==
null || !check.Contains("Continue"))//得到server确认后才继续上传
{
errmsg = "client已成功发送请求,但server没有响应。";
return 0;
}
if (paranames !=
null)
{
soc.Send(textbyte, textbyte.Length,
SocketFlags.None);//发送表单參数
}
if (files !=
null)
{//依次发送文件
for (int i = 0; i < data.Count; i++)
{
int size = 0;
FileStream fs =File.Open(files[i],FileMode.Open,
FileAccess.Read,FileShare.Read);
soc.Send(data[i], data[i].Length,
SocketFlags.None);
byte[] buff =newbyte[1024];
size = fs.Read(buff, 0, 1024);
while (size > 0)
{
soc.Send(buff, size,
SocketFlags.None);
size = fs.Read(buff, 0, 1024);
}
fs.Close();
}
}
soc.Send(boundary, boundary.Length,
SocketFlags.None);
return 1;
}
catch (Exception exc)
{
errmsg = exc.Message.ToString();
return 0;
}
}
利用socket模拟http的混合表单上传(在一个请求中提交表单并上传多个文件)的更多相关文章
- gerrit上的commit msg中关联jira单号(含gerrit的安装)
这个问题折腾了很久,前期后后大概一个月吧,终于搞定了,查了很多资料,有的不完整,有的完全就不能用,有的没说完整,所以一定要记录下来,我的心血啊. 由于公司在用的gerrit的是正式环境中的,大家都在使 ...
- MVC中提交表单的4种方式
一,MVC HtmlHelper方法 Html.BeginForm(actionName,controllerName,method,htmlAttributes){} BeginRouteForm ...
- 学习日记3、投机取巧使两个表的数据同时在一个treeGrid中显示
不多说了直接上代码, $('#List').treegrid({ url: '@Url.Action("GetList")', width: $(window).width() - ...
- EasyUI加zTree使用解析 easyui修改操作的表单回显方法 验证框提交表单前验证 datagrid的load方法
带参提交一次查询,从服务器加载新数据.这是一个神奇的方法 $('#dg').datagrid('load',{ code: '01', name: 'name01' }); easyui修改操作的回显 ...
- Spring MVC中 提交表单报错400
背景: 在写SpringMVC表单提交的代码的时,在最后点击提交的时候总是会出现400的错误 原因: 主要原因就是表单提交的数据和对应实体类的属性无法完全匹配 解决方案: 查看我们提交的数据是否完全和 ...
- Java后台防止客户端重复请求、提交表单
前言 在Web / App项目中,有一些请求或操作会对数据产生影响(比如新增.删除.修改),针对这类请求一般都需要做一些保护,以防止用户有意或无意的重复发起这样的请求导致的数据错乱. 常见处理方案 1 ...
- vue中提交表单后如何清空
只需要在提交方法里写上this.form={brand_right:0}即可.
- Java Web中提交表单之后跳转到WebContent目录下的子目录里的jsp文件
最近在做一个系统,需要完成登录动能进行跳转到另一个页面.在这个项目里面,我把 jsp,css,js文件都统一放在 WebContent 目录下的一个 WebPage 里面. 按照以前的习惯,写好了 s ...
- mysql:把DB1中A表a字段替换为DB2中B表b字段
UPDATE DB1.A SET a = ( SELECT b FROM DB2.B WHERE B.Id = A.id) 实例: UPDATE wordpress.`wp_posts` SET po ...
随机推荐
- How Javascript works (Javascript工作原理) (九) 网页消息推送通知机制
个人总结: 1.介绍了网页消息推送通知机制 全文地址:https://github.com/Troland/how-javascript-works 这是 JavaScript 工作原理的第九章. 现 ...
- NOIp模拟赛三十四(yxq供题)
毒瘤yxq! 毒瘤yxq! 毒瘤yxq! 据yxq自己说,林导让他出题的时候要求是“代码量少”,“思维难度高”,“不涉及太复杂的算法”,而且“最好要让myh有一题做不出来”(狙击myh).于是今天的题 ...
- 【Python】包管理工具pip
一.pip的安装 1. 将"D:\Python27\" 和 "D:\Python27\Scripts"设置到环境变量当中 2. 安装setup tools 将 ...
- JDBC读写MySQL的大字段数据
JDBC读写MySQL的大字段数据 不管你是新手还是老手,大字段数据的操作常常令你感到很头痛.因为大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式 来处理的.而非一般的字段 ...
- 关于Subversion主从备份方式的调整(全量、增量脚本)更新
本文引用于http://blog.chinaunix.net/uid-25266990-id-3369172.html 之前对Subversion服务器作了迁移,关于SVN的架构也走了调整,有单一的服 ...
- vue非父子组件间传参问题
最近在使用vue进行开发,遇到了组件之间传参的问题,此处主要是针对非父子组件之间的传参问题进行总结,方法如下:一.如果两个组件用友共同的父组件,即 FatherComponent.vue代码 < ...
- POJ 2739 Sum of Consecutive Prime Numbers(素数)
POJ 2739 Sum of Consecutive Prime Numbers(素数) http://poj.org/problem? id=2739 题意: 给你一个10000以内的自然数X.然 ...
- 公布Qt Widgets桌面应用程序的方法
公布Qt Widgets桌面应用程序的方法 Qt是一款优秀的跨平台开发框架,它能够在桌面.移动平台以及嵌入式平台上执行.眼下Qt 5介绍程序公布的文章帖子比較少.大家又很想要知道怎样公布Qt应用程序, ...
- android 自己定义dialog并实现失去焦点(背景透明)的功能
前言:因为在项目中须要用到更新显示动画的需求,所以想到了dialog,自己定义dialog不难.网上教程非常多,可是在实现dialog背景透明的需求时,遇到了一点问题.网上的一些方法在我的机器上并没有 ...
- MongoDB Shell (mongo)
https://docs.mongodb.com/getting-started/shell/client/ The mongo shell is an interactive JavaScript ...