C# HttpWebRequest 后台调用接口上传大文件以及其他参数
直接上代码,包各位看客能用!!!
1.首先请求参数的封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /// <summary> /// 上传文件 - 请求参数类 /// </summary> public class UploadParameterType { public UploadParameterType() { FileNameKey = "fileName" ; Encoding = Encoding.UTF8; PostParameters = new Dictionary< string , string >(); } /// <summary> /// 上传地址 /// </summary> public string Url { get ; set ; } /// <summary> /// 文件名称key /// </summary> public string FileNameKey { get ; set ; } /// <summary> /// 文件名称value /// </summary> public string FileNameValue { get ; set ; } /// <summary> /// 编码格式 /// </summary> public Encoding Encoding { get ; set ; } /// <summary> /// 上传文件的流 /// </summary> public Stream UploadStream { get ; set ; } /// <summary> /// 上传文件 携带的参数集合 /// </summary> public IDictionary< string , string > PostParameters { get ; set ; } } |
2.HttpWebRequest 封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | /// <summary> /// Http上传文件类 - HttpWebRequest封装 /// </summary> public class HttpUploadClient { /// <summary> /// 上传执行 方法 /// </summary> /// <param name="parameter">上传文件请求参数</param> public static string Execute(UploadParameterType parameter) { using (MemoryStream memoryStream = new MemoryStream()) { // 1.分界线 string boundary = string .Format( "----{0}" , DateTime.Now.Ticks.ToString( "x" )), // 分界线可以自定义参数 beginBoundary = string .Format( "--{0}\r\n" , boundary), endBoundary = string .Format( "\r\n--{0}--\r\n" , boundary); byte [] beginBoundaryBytes = parameter.Encoding.GetBytes(beginBoundary), endBoundaryBytes = parameter.Encoding.GetBytes(endBoundary); // 2.组装开始分界线数据体 到内存流中 memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length); // 3.组装 上传文件附加携带的参数 到内存流中 if (parameter.PostParameters != null && parameter.PostParameters.Count > 0) { foreach (KeyValuePair< string , string > keyValuePair in parameter.PostParameters) { string parameterHeaderTemplate = string .Format( "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n{2}" , keyValuePair.Key, keyValuePair.Value, beginBoundary); byte [] parameterHeaderBytes = parameter.Encoding.GetBytes(parameterHeaderTemplate); memoryStream.Write(parameterHeaderBytes, 0, parameterHeaderBytes.Length); } } // 4.组装文件头数据体 到内存流中 string fileHeaderTemplate = string .Format( "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n" , parameter.FileNameKey, parameter.FileNameValue); byte [] fileHeaderBytes = parameter.Encoding.GetBytes(fileHeaderTemplate); memoryStream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length); // 5.组装文件流 到内存流中 byte [] buffer = new byte [1024 * 1024 * 1]; int size = parameter.UploadStream.Read(buffer, 0, buffer.Length); while (size > 0) { memoryStream.Write(buffer, 0, size); size = parameter.UploadStream.Read(buffer, 0, buffer.Length); } // 6.组装结束分界线数据体 到内存流中 memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); // 7.获取二进制数据 byte [] postBytes = memoryStream.ToArray(); memoryStream.Close(); GC.Collect(); // 8.HttpWebRequest 组装 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create( new Uri(parameter.Url, UriKind.RelativeOrAbsolute)); webRequest.AllowWriteStreamBuffering = false ; webRequest.Method = "POST" ; webRequest.Timeout = 1800000; webRequest.ContentType = string .Format( "multipart/form-data; boundary={0}" , boundary); webRequest.ContentLength = postBytes.Length; if (Regex.IsMatch(parameter.Url, "^https://" )) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult; } // 9.写入上传请求数据 using (Stream requestStream = webRequest.GetRequestStream()) { requestStream.Write(postBytes, 0, postBytes.Length); requestStream.Close(); } // 10.获取响应 using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) { using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), parameter.Encoding)) { string body = reader.ReadToEnd(); reader.Close(); return body; } } } } /// <summary> /// 上传执行 方法 /// </summary> /// <param name="parameter">上传文件请求参数</param> public static string Execute2(UploadParameterType parameter) { // 1.分界线 string boundary = string .Format( "----{0}" , DateTime.Now.Ticks.ToString( "x" )), // 分界线可以自定义参数 beginBoundary = string .Format( "--{0}\r\n" , boundary), endBoundary = string .Format( "\r\n--{0}--\r\n" , boundary); byte [] beginBoundaryBytes = parameter.Encoding.GetBytes(beginBoundary), endBoundaryBytes = parameter.Encoding.GetBytes(endBoundary); byte [] postBytes = new byte [] { }; using (MemoryStream memoryStream = new MemoryStream()) { // 2.组装开始分界线数据体 到内存流中 memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length); // 3.组装 上传文件附加携带的参数 到内存流中 if (parameter.PostParameters != null && parameter.PostParameters.Count > 0) { foreach (KeyValuePair< string , string > keyValuePair in parameter.PostParameters) { string parameterHeaderTemplate = string .Format( "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n{2}" , keyValuePair.Key, keyValuePair.Value, beginBoundary); byte [] parameterHeaderBytes = parameter.Encoding.GetBytes(parameterHeaderTemplate); memoryStream.Write(parameterHeaderBytes, 0, parameterHeaderBytes.Length); } } // 4.组装文件头数据体 到内存流中 string fileHeaderTemplate = string .Format( "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n" , parameter.FileNameKey, parameter.FileNameValue); byte [] fileHeaderBytes = parameter.Encoding.GetBytes(fileHeaderTemplate); memoryStream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length); // 5.组装结束分界线数据体 到内存流中 //memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); // 6.获取二进制数据 postBytes = memoryStream.ToArray(); } // 7.HttpWebRequest 组装 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create( new Uri(parameter.Url, UriKind.RelativeOrAbsolute)); //对发送的数据不使用缓存【重要、关键】 webRequest.AllowWriteStreamBuffering = false ; webRequest.Method = "POST" ; webRequest.Timeout = 1800000; webRequest.ContentType = string .Format( "multipart/form-data; boundary={0}" , boundary); webRequest.ContentLength = postBytes.Length + parameter.UploadStream.Length+endBoundaryBytes.Length; if (Regex.IsMatch(parameter.Url, "^https://" )) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult; } // 8.组装文件流 byte [] buffer = new byte [1024 * 1024 * 1]; int size = parameter.UploadStream.Read(buffer, 0, buffer.Length); Stream requestStream = webRequest.GetRequestStream(); requestStream.Write(postBytes, 0, postBytes.Length); while (size > 0) { requestStream.Write(buffer, 0, size); size = parameter.UploadStream.Read(buffer, 0, buffer.Length); } requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); requestStream.Close(); // 9.获取响应 using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) { using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), parameter.Encoding)) { string body = reader.ReadToEnd(); reader.Close(); return body; } } } static bool CheckValidationResult( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true ; } } |
HttpUploadClient类中两个Execute2,参考网上,大都用第一个,如果上传小文件没问题,要是比较大(百兆以上)就会内存溢出,然后就用流方式。思路是一样的
3.调用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | using (FileStream fs = new FileStream( @"C:\\test.zip" , FileMode.Open, FileAccess.Read)) { Dictionary< string , string > postParameter = new Dictionary< string , string >(); postParameter.Add( "name" , "heshang" ); postParameter.Add( "param" , "1 2 3" ); string result = HttpUploadClient.Execute( new UploadParameterType { Url = url, UploadStream = fs, FileNameValue = "test.zip" , PostParameters = postParameter }); } |
4.接口服务后台接受请求时:
1 2 3 4 5 6 7 8 | public IHttpActionResult Post() { HttpPostedFile file = HttpContext.Current.Request.Files[0]; string pyPath = HttpContext.Current.Request[ "name" ]; string Params = HttpContext.Current.Request[ "params" ]; file.SaveAs( "C:\\test.zip" ); return Ok( "" ); } |
5.完美解决大文件上传
分类:
.NET后端开发
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?