利用socket模拟http的混合表单上传(在一个请求中提交表单并上传多个文件)

Posted zhchoutai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用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的混合表单上传(在一个请求中提交表单并上传多个文件)的主要内容,如果未能解决你的问题,请参考以下文章

js 上传文件模拟Form 表单

混合表单文件上传到数据库(基于TOMCAT)

如何在 Python 中模拟 post 表单来上传文件

15. 利用ajax jquery 上传文件

利用Socket和IO流实现文件的上传与下载

文件各种上传,离不开的表单