通过C#的HttpClient模拟form表单请求

post提交表单一般无非是一般text文本和文件类型,如下

<input type="file"/>
<input type="text"/>

如果模拟post提交表单的过程(类似于HTML表单提交),该怎么做呢

这里就需要用到HttpClietn类

首先我们需要一个类去包装这些需要上载的数据,例如

   /// <summary>
    /// 包装Data数据的Model
    /// </summary>
    public class SendData
    {
        /// <summary>
        /// 多个文件的
        /// </summary>
        public List<HttpPostedFileBase> FileList { get; set; }

        /// <summary>
        /// 单个文件
        /// </summary>
        public HttpPostedFileBase File{ get; set; }

      /// <summary>
        /// 字节类型
        /// </summary>
        public byte[] ByteBinary { get; set; }

        /// <summary>
        /// long类型
        /// </summary>public long IconId { get; set; }

        /// <summary>
        /// 字符串类型
        /// </summary>public string Title { get; set; }
      /// <summary>
        /// 时间类型
        /// </summary>public DateTime PushTime { get; set; }

        /// <summary>
        /// bool类型
        /// </summary>public bool PushNow { get; set; }
      /// <summary>
        /// long的集合类型
        /// </summary>
        List<long> TestLong { get; set; } = new List<long> { 1, 2, 3, 4, 5, 6 };

        /// <summary>
        /// string的集合类型
        /// </summary>
        List<string> TestString { get; set; } = new List<string> {"1","2","3" };

    }
SendToWebByHttpClient("www.....",new SendData{
            FileList =要提交的数据,
            File=要提交的数据,
            ByteBinary=要提交的数据,
              .
              .
              .
              .
              .            })

请求帮助     

       /// <summary> 模拟表单请求/liuyl/2017/09/1 /// </summary>        
      /// <typeparam name="T"></typeparam>
         /// <param name="url"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ErrorCode SendToWebByHttpClient<T>(string url, T value)
        {
            var modelType = typeof(T);
            using (var client = new HttpClient())
            using (var formData = new MultipartFormDataContent())
            {
          //遍历SendData的所有成员
                foreach (var item in modelType.GetProperties())
                {
                    HttpContent content;
            //文件的处理(这里需要特别注意,流只能读取一次,因为读取之后会把Stream.Positon(当前流中的位置)置为最后读取的位置,除非置为0,第二次才可读到)
                    if (item.PropertyType == typeof(HttpPostedFileBase) && item.GetValue(value) != null)
                    {
                        #region Stream请求
                        //Stream塞进Content会会导致读取这个流,所以之后不能再第二次利用
                        var model = (HttpPostedFileBase)item.GetValue(value);
                        content = new StreamContent(model.InputStream, model.ContentLength);                       
               content.Headers.ContentType = MediaTypeHeaderValue.Parse(model.ContentType);//ContentType必须赋值,否则文件接收不到此属性
                        content.Headers.ContentLength = model.ContentLength;//ContentLength可不显式的赋值,会自动读取给StreamContent的内容长度
                        formData.Add(content, item.Name, model.FileName);//文件类型,第三个参数必须要赋值,否则不认为这是一个文件

                        #endregion

                        #region 字节方式请求
                        //var model = (HttpPostedFileBase)item.GetValue(value);
                        //MemoryStream fileTarget = new MemoryStream();
                        //model.InputStream.CopyTo(fileTarget);
                        //content = new ByteArrayContent(fileTarget.ToArray());
                        //content.Headers.ContentType = MediaTypeHeaderValue.Parse(model.ContentType);
                        //content.Headers.ContentLength = model.ContentLength;
                        //formData.Add(content, item.Name, model.FileName);

                        #endregion
                    }
                    //文件的处理
                    else if (item.PropertyType == typeof(HttpPostedFileWrapper) && item.GetValue(value) != null)
                    {
                        #region Stream请求
                        var model = (HttpPostedFileWrapper)item.GetValue(value);
                        content = new StreamContent(model.InputStream, model.ContentLength);
                        content.Headers.ContentType = MediaTypeHeaderValue.Parse(model.ContentType);
                        content.Headers.ContentLength = model.ContentLength;
                        formData.Add(content, item.Name, model.FileName);

                        #endregion
                        #region 字节方式请求
                        //var model = (HttpPostedFileWrapper)item.GetValue(value);
                        //MemoryStream fileTarget = new MemoryStream();
                        //model.InputStream.CopyTo(fileTarget);
                        //content = new ByteArrayContent(fileTarget.ToArray());
                        //content.Headers.ContentType = MediaTypeHeaderValue.Parse(model.ContentType);
                        //content.Headers.ContentLength = model.ContentLength;
                        //formData.Add(content, item.Name, model.FileName);

                        #endregion

                    }
                    //文件集合的处理
                    else if (item.PropertyType == typeof(List<HttpPostedFileBase>) && item.GetValue(value) != null)
                    {
                        foreach (var child in ((List<HttpPostedFileBase>)item.GetValue(value)))
                        {
                            #region Stream请求
                            content = new StreamContent(child.InputStream, child.ContentLength);
                            content.Headers.ContentType = MediaTypeHeaderValue.Parse(child.ContentType);
                            content.Headers.ContentLength = child.ContentLength;
                            formData.Add(content, item.Name, child.FileName);
                            #endregion

                            #region 字节方式请求
                            //MemoryStream fileTarget = new MemoryStream();
                            //child.InputStream.CopyTo(fileTarget);
                            //content = new ByteArrayContent(fileTarget.ToArray());
                            //content.Headers.ContentType = MediaTypeHeaderValue.Parse(child.ContentType);
                            //content.Headers.ContentLength = child.ContentLength;
                            //formData.Add(content, item.Name, child.FileName);

                            #endregion
                        }
                    }
                    //如果执意响应方是接收字节类型,那传输时不能用ByteArrayContent去填充,否则接收方认为这是一个非法数据,故要传base64格式,接收方会自动把base64转成字节接收
                    else if (item.PropertyType == typeof(byte[]) && item.GetValue(value) != null)
                    {
                        content = new StringContent(Convert.ToBase64String((byte[])item.GetValue(value)));
                        formData.Add(content, item.Name);
                    }
                    //其他类型统一按字符串处理(DateTime,Enum;long ;bool;int...)
                    else if (item.GetValue(value) != null && (item.PropertyType != typeof(byte[]) || item.PropertyType != typeof(HttpPostedFileBase)))
                    {
                        content = new StringContent(((string)item.GetValue(value).ToString()));
                        formData.Add(content, item.Name);
                    }
                }

                var response = client.PostAsync(url, formData).Result;

                if (!response.IsSuccessStatusCode)
                {
            //以下根据自己业务处理返回值
                    var obj = JsonHandler.DeserializeObject<BaseViewModel>(response.ToString());
                    if (obj != null)
                    {
                        var result = obj.ErrResult;
                        if (result.ErrorCode != ErrorCode.OK)
                        {
                            foreach (var message in result.Messages)
                            {
                                _Error += message;
                            }
                            return result.ErrorCode;
                        }
                    }
                }
                return ErrorCode.OK;
            }
        }
partial class InternalController:Controller
    {
        /// <summary>
        /// 接收方
        /// </summary>
        /// <param name="model"></param>
        /// <returns>HTTP200</returns>
        [HttpPost]
        [ValidateInput(false)]//忽略安全检查,要配合在<system.web>中加入<httpRuntime requestValidationMode =“2.0”/>方可启用,详情参考:了解MVC的请求验证
        public ActionResult AddOfficialNews(SendData model)
        {
            try
            {
                if (!ModelState.IsValid)
                    return SendJsonResult(ErrorCode.InvalidOperation);
              .....
        }
     }  
  }

 需要特别注意(特别注意点在请求帮助类中已用黄底背景标注):

如果是上传的文件类型,一定不能在塞入StreamContent等之前进行过读取操作,否则此处将读不到流数据

 参考:

https://stackoverflow.com/questions/16416601/c-sharp-httpclient-4-5-multipart-form-data-upload

猜你喜欢

转载自blog.csdn.net/lishimin1012/article/details/82801046