C# HTTP系列12 以form-data方式上传键值对集合到远程服务器
使用multipart/form-data方式提交数据与普通的post方式有一定区别。multipart/form-data的请求头必须包含一个特殊的头信息:Content-Type,其值必须为multipart/form-data。另外还需要规定一个内容分割符用于分割请求体中的多个post的内容,如文件内容和文本内容,只有这样服务端才能正常解析数据。但是,multipart/form-data的基础还是post,它是由post方法来实现的。
点击【Code】按钮,打开如下窗体:
可以看到 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
以及蓝色框内的用分隔符分割的请求体中的内容。
在某些应用场景下,表单数据以键值对集合存储,然后将键值对集合上传到远程服务器。
通用方法如下:
1 /// <summary> 2 /// HTTP请求(包含表单数据) 3 /// </summary> 4 /// <param name="url">请求目标URL</param> 5 /// <param name="kvDatas">请求时表单键值对数据</param> 6 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param> 7 /// <returns></returns> 8 public HttpResult UploadForm(string url, NameValueCollection kvDatas, string method = WebRequestMethods.Http.Post) 9 { 10 HttpResult httpResult = new HttpResult(); 11 HttpWebRequest httpWebRequest = null; 12 13 try 14 { 15 httpWebRequest = WebRequest.Create(url) as HttpWebRequest; 16 httpWebRequest.Method = method; 17 httpWebRequest.Headers = HeaderCollection; 18 httpWebRequest.CookieContainer = CookieContainer; 19 httpWebRequest.ContentType = HttpContentType.WWW_FORM_URLENCODED; 20 httpWebRequest.UserAgent = _userAgent; 21 httpWebRequest.AllowAutoRedirect = _allowAutoRedirect; 22 httpWebRequest.ServicePoint.Expect100Continue = false; 23 24 if (kvDatas != null) 25 { 26 StringBuilder sbKV = new StringBuilder(); 27 foreach (string key in kvDatas.Keys) 28 { 29 sbKV.AppendFormat("{0}={1}&", Uri.EscapeDataString(key), Uri.EscapeDataString(kvDatas[key])); //注意中文编码 30 } 31 32 httpWebRequest.AllowWriteStreamBuffering = true; 33 using (Stream requestStream = httpWebRequest.GetRequestStream()) 34 { 35 requestStream.Write(EncodingType.GetBytes(sbKV.ToString()), 0, sbKV.Length - 1); 36 requestStream.Flush(); 37 } 38 } 39 40 HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; 41 if (httpWebResponse != null) 42 { 43 GetResponse(ref httpResult, httpWebResponse); 44 httpWebResponse.Close(); 45 } 46 } 47 catch (WebException webException) 48 { 49 GetWebExceptionResponse(ref httpResult, webException); 50 } 51 catch (Exception ex) 52 { 53 GetExceptionResponse(ref httpResult, ex, method, HttpContentType.WWW_FORM_URLENCODED); 54 } 55 finally 56 { 57 if (httpWebRequest != null) 58 { 59 httpWebRequest.Abort(); 60 } 61 } 62 63 return httpResult; 64 }
1、向 NameValueCollection 类中添加项时,键可以重复。
2、如果添加了C#中的某些关键字作为集合的键则会报错,解决方法是,给关键字添加前缀或者后缀,在解析时再去除前缀或者后缀。
借助于上述方法,又衍生出一个重载方法:
1 /// <summary> 2 /// HTTP请求(包含表单数据) 3 /// </summary> 4 /// <param name="url">请求目标URL</param> 5 /// <param name="kvDatas">请求时表单键值对数据</param> 6 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param> 7 /// <returns></returns> 8 public HttpResult UploadForm(string url, Dictionary<string, string> kvDatas, string method = WebRequestMethods.Http.Post) 9 { 10 var nvc = kvDatas.ToNameValueCollection(); 11 12 return UploadForm(url, nvc, method); 13 }
Dictionary 字典中不能添加重复的键。
Dictionary 转换成 NameValueCollection 集合的扩展方法如下:
1 /// <summary> 2 /// 自定义扩展方法:将字典转换为 NameValueCollection 集合对象 3 /// </summary> 4 /// <param name="dict">扩展对象</param> 5 /// <returns></returns> 6 public static NameValueCollection ToNameValueCollection<TKey, TValue>(this IDictionary<TKey, TValue> dict) 7 { 8 if (dict == null) 9 { 10 return null; 11 } 12 13 var nameValueCollection = new NameValueCollection(); 14 15 foreach (var item in dict) 16 { 17 string value = null; 18 if (item.Value != null) 19 { 20 value = item.Value.ToString(); 21 } 22 23 nameValueCollection.Add(item.Key.ToString(), value); 24 } 25 26 return nameValueCollection; 27 }
源码下载链接: https://pan.baidu.com/s/1bYh2COYxxeG1WIYJt6Wsnw 提取码: ysqd
成在管理,败在经验;嬴在选择,输在不学! 贵在坚持!
个人作品
BIMFace.SDK.NET
开源地址:https://gitee.com/NAlps/BIMFace.SDK
系列博客:https://www.cnblogs.com/SavionZhang/p/11424431.html
系列视频:https://www.cnblogs.com/SavionZhang/p/14258393.html
技术栈
1、Visual Studio、.NET Core/.NET、MVC、Web API、RESTful API、gRPC、SignalR、Java、Python
2、jQuery、Vue.js、Bootstrap、ElementUI
3、数据库:分库分表、读写分离、SQLServer、MySQL、PostgreSQL、Redis、MongoDB、ElasticSearch、达梦DM
4、架构:DDD、ABP、SpringBoot、jFinal
5、环境:跨平台、Windows、Linux、Nginx
6、移动App:Android、IOS、HarmonyOS、微信小程序、钉钉、uni-app、MAUI
分布式、高并发、云原生、微服务、Docker、CI/CD、DevOps、K8S;Dapr、RabbitMQ、Kafka、RPC、Elasticsearch。
欢迎关注作者头条号 张传宁IT讲堂,获取更多IT文章、视频等优质内容。
出处:www.cnblogs.com/SavionZhang
作者:张传宁 技术顾问、培训讲师、微软MCP、系统架构设计师、系统集成项目管理工程师、科技部创新工程师。
专注于企业级通用开发平台、工作流引擎、自动化项目(代码)生成器、SOA 、DDD、 云原生(Docker、微服务、DevOps、CI/CD);PDF、CAD、BIM 审图等研究与应用。
多次参与电子政务、图书教育、生产制造等企业级大型项目研发与管理工作。
熟悉中小企业软件开发过程:可行调研、需求分析、架构设计、编码测试、实施部署、项目管理。通过技术与管理帮助中小企业实现互联网转型升级全流程解决方案。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如有问题,可以通过邮件905442693@qq.com联系。共同交流、互相学习。
如果您觉得文章对您有帮助,请点击文章右下角【推荐】。您的鼓励是作者持续创作的最大动力!