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

在很多企业级应用中,我们都没法直接通过开发语言sdk包封装的http工具来模拟http复合表单(multipart/form-data),特别是在跨语言跨平台的编程过程中,其实实现方案并不复杂,只要你了解了http协议中复合表单的报文结构就很简单了:

        httpheader

        ------时间戳------

        表单参数1

       ------时间戳------

       表单参数2

      ------时间戳------

      文件1的描述+二进制信息

     ------时间戳------

     文件2的描述+二进制信息

 

    下面我们进一步以一段c#的代实例码来演示下这个结构:

       

        ///<summary>

        ///向服务器发送混合型的请求,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 =new List<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 =new StringBuilder();

                    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");//注明要在收到服务器的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"))//得到服务器确认后才继续上传

                {

                    errmsg = "客户端已成功发送请求,但服务器没有响应!";

                    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 =new byte[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;

            }

        }

时间: 2024-10-27 21:48:23

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

myclipse10在jsp中提交表单出现中文乱码

问题描述 myclipse10在jsp中提交表单出现中文乱码 在Myclipse10中,jsp提交了一个表单, 提交到另一个表单后,用 (String)request.getParameter(""stuname"") 获取时出现了中文乱码,无法显示正常的汉字;jsp字体已经设置为utf-8,也写了request.setCharacterEncoding(""utf-8"");求问题原因. 解决方案 jsp头是这样吗? <

在HTML5中提交表单数据以JSON编码格式传输

以JSON编码格式提交表单数据是HTML5对WEB发展进化的又一大贡献,以前我们的HTML表单数据是通过key-value方式传输的服务器端,这种形式的传输对数据组织缺乏管理,形式十分原始.而新出现的JSON格式提交表单数据方法,将表单里的所有数据转化的具有一定规范的JSON格式,然后传输的服务器端.服务器端接收到的数据是直接可以使用的合格JSON代码. 如何声明以JSON格式提交表单 大家应该对如何用表单上传一个文件的写法很熟悉,它需要在HTML中form标记上添加 enctype="mult

listview-将两张表的数据展示在一个ListView中

问题描述 将两张表的数据展示在一个ListView中 数据库中的数据如图所示,一共有5张表,三个数据表以及两个关系表.我现在需要将所有的project和exam读取出来然后将其中的name和description显示在同一个ListView中,根据数据表中的session sort no来排序. 现在的问题: 1.如何同时读取所有的exam和project数据并根据session sort no来排序呢?因为数据比较多,所以应该不会一次性完成读取,而是用类似SimpleCursorAdapter

高级表单验证-针对多次提交表单

表单验证|高级|提交表单 每个开发人员面对的困难是预测用户能够或是将要做什么--这对于网络开发人员来说就更为困 难,因为他的预测必须考虑到Web 的多样性和缺乏真正的session控制机制.如果你已经创建过一个使用表单的ASP应用程序,也许你已经遇到过一些奇怪的问题,如数据传输两次,接收数据不完整,或者用户报告表单显示不正确.尽管你也插入了确认数据所需的所有客户机端和服务器端的脚本,表单仍然会发生许多异常情况.这些异常情况与意外用户行为或浏览器书签的误使用有关.本文将集中解决一些容易引起表单问题

c#中用axWebBrowser中提交表单,或点击某个对象

web|对象|提交表单 dddd.htm <TR bgColor=#ffffff width="100%"><TD align=middle colSpan=2><form id="form1"> <INPUT language=javascript class=button id=Btton style="BORDER-TOP-STYLE: groove; BORDER-RIGHT-STYLE: groove;

ASP.net中用axWebBrowser中提交表单

asp.net|web|提交表单 <TR bgColor=#ffffff width="100%"><TD align=middle colSpan=2><form id="form1"><INPUT language=javascript class=button id=Btton style="BORDER-TOP-STYLE: groove; BORDER-RIGHT-STYLE: groove; BORDE

详细分析使用AngularJS编程中提交表单的方式

这篇文章主要介绍了详细分析使用AngularJS提交表单的方式,AngularJS是非常热门的JavaScript库,文中展示了AngularJS在前端与后端的PHP进行交互的场景,需要的朋友可以参考下 在AngularJS出现之前,很多开发者就面对了表单提交这一问题.由于提交表单的方式繁杂而不同,很容易令人疯掉--然而现在看来,依然会让人疯掉. 今天,我们会看一下过去使用PHP方式提交的表单,现在如何将其转换为使用Angular提交.使用Angular来处理表单,对我而言,是一个"啊哈&quo

PHP利用socket模拟post之fsockopen发送数据

 代码如下 复制代码 POST /目的程序 HTTP/1.1 Accept: */* Referer: http://www.111cn.net Accept-Language: zh-cn,en-us;q=0.5 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; .NET CLR 1.0.3705; .NET CLR 1.1.432

在JSP文件中的同一个form表单有多个用来提交表单值的按钮,用户可以通过不同的按钮提交表单,需要调用Action中的不同处理方法,该怎么使用动态方法调用?

问题描述 Action 问题补充:是struts2 怎么修改jsP动态form的action名称呀? 解决方案 function formSubmit(){document.form1.method="post"; var url ="<%=request.getContextPath()%>/hrt/chartSichuan.do?method=recordList"; document.form1.action= url; document.form