zoukankan      html  css  js  c++  java
  • 利用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(" " + strBoundary +" ");

                length += boundary.Length;

                //构造时间戳

     

                //载入表单參数信息

                if (paranames != null)

                {

                    text = new StringBuilder();

                    for (int i = 0; i < paranames.Length; i++)

                    {

                        text.Append("--");

                        text.Append(strBoundary);//加入时间戳

                        text.Append(" ");

                        text.Append("Content-Disposition: form-data; name="" + paranames[i] +"" ");

                        text.Append(paravalues[i]);

                        text.Append(" ");

                    }

                    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(" --");

                            sbfile.Append(strBoundary);//加入时间戳                       

                            sbfile.Append(" ");

                            sbfile.Append("Content-Disposition: form-data; name="");

                            sbfile.Append("file");

                            sbfile.Append(""; filename="");

                            sbfile.Append(Path.GetFileName(files[i]));

                            sbfile.Append(""");

                            sbfile.Append(" ");

                            sbfile.Append("Content-Type: ");

                            sbfile.Append("application/octet-stream");

                            sbfile.Append(" Content-Length:");

                            sbfile.Append(fs.Length.ToString());

                            sbfile.Append(" ");

                            sbfile.Append(" ");

                            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 ");

                http.Append("Content-Type:multipart/form-data;boundary=");

                http.Append(strBoundary);

                http.Append(" ");

                http.Append("Host:" + ipaddress +":" + tcpport.ToString() +" ");

                http.Append("Content-Length:");

                http.Append(length.ToString());

                http.Append(" ");

                http.Append("Expect: 100-continue ");//注明要在收到server的continue消息后才继续上传http消息体

                http.Append("Connection: Keep-Alive ");

                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;

                }

            }

     

  • 相关阅读:
    UniEAP V4 开发实践说明文档
    SI_WorkShop_V4安装手册
    unieap platform eclipse.ini vm设置
    asp.net 配置 web.config 禁用VS2013自带的Browser Link功能
    unieap 建库
    onserverclick
    工作中记录的命令和知识点(不断更新)
    CentOS 下做端口映射/端口转发
    DELL服务器硬件信息采集SHELL脚本
    Linux中变量#,@,0,1,2,*,$$,$?的意思
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8438748.html
Copyright © 2011-2022 走看看