• 通过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

  • 相关阅读:
    02.ZooKeeper的Java客户端使用
    01.ZooKeeper安装和介绍
    02.Elasticsearch入门
    01.Elasticsearch安装
    01.ActiveMQ安装部署
    springboot项目打包时提示“程序包xxx不存在,找不到符号”
    Eclipse提交git代码 报错authentication not supported
    Eclipse提交git代码 报错authentication not supported
    utf8mb4_general_ci报错解决方案
    mysql开启远程访问
  • 原文地址:https://www.cnblogs.com/xiaoliangge/p/7522828.html
Copyright © 2020-2023  润新知