C#上传文件 HttpWebRequest改为HttpClient
1、先声明HttpClient是.net 4.5及其以后的版本中引入的,要使用的话必须是4.5及之后的版本才行。
2、原因
再说下我为什么要把原始的HttpWebRequest改为HttpClient的原因,内存问题,是的,用HttpWebRequest上传文件,就如果100M的文件,2,3次就能把内存干爆,不知道为啥HttpWebRequest方法上传100M的文件,内存会增加300M,相当于加载了3次(我调代码发现的),而且方法里我把所有改置空的,要释放的都加了,然后无非就是多了几次,依然能拉爆软件的内存(因为测试可不会管你什么限制啥的,一次上传十几个百M的文件很正常)。而且现在大多数程序都是32位的,为了兼容软件使用的外部插件嘛没办法,这就导致能用的内存上下在1G左右(我们的软件,其他的不清楚,但32位上限确实低的多)。
然后用HttpClient你会发现,就简单的几行代码,几乎没有需要置空或释放的,内部自己给你处理了。改完发现随便折腾没毛病,真是气死个人,有时候降维打击最为致命,就像二战时德国的步坦结合的闪电战,把还在延用一战阵地战的号称最强陆军的法国,几个月就打穿了。
3、下面直接贴代码了,分两部分,上面是原始的HttpWebRequest,下面的改的HttpClient的,供大家借鉴
HttpWebRequest:
public string PostContainFiles(string url, Dictionary<string, string> formFields, Dictionary<string, byte[]> attachments) { string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; using (Stream memStream = new System.IO.MemoryStream()) { var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--"); string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; //如果formFields不为空时 此项拼接在首位使用该字符串 string formdataTemplateFirst = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; bool ret = true;
//formFields是接口的入参 if (formFields != null) { foreach (string key in formFields.Keys) { string formitem = string.Empty; if (ret) { formitem = string.Format(formdataTemplateFirst, key, formFields[key]); ret = false; } else { formitem = string.Format(formdataTemplate, key, formFields[key]); } byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); memStream.Write(formitembytes, 0, formitembytes.Length); } } string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; if (attachments != null && attachments.Any()) { foreach (var item in attachments) { memStream.Write(boundarybytes, 0, boundarybytes.Length); var header = string.Format(headerTemplate, item.Key, item.Key); var headerbytes = System.Text.Encoding.UTF8.GetBytes(header); memStream.Write(headerbytes, 0, headerbytes.Length); memStream.Write(item.Value, 0, item.Value.Length); } attachments.Clear(); attachments = null; } memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); endBoundaryBytes = null; request.ContentLength = memStream.Length; using (Stream requestStream = request.GetRequestStream()) { memStream.Position = 0; byte[] tempBuffer = new byte[memStream.Length]; memStream.Read(tempBuffer, 0, tempBuffer.Length); memStream.Close(); requestStream.Write(tempBuffer, 0, tempBuffer.Length); requestStream.Flush(); tempBuffer = null; } memStream.Flush(); } using (var response = request.GetResponse()) { using (Stream stream2 = response.GetResponseStream()) { using (StreamReader reader2 = new StreamReader(stream2)) { string str = reader2.ReadToEnd(); return str; } } } }
HttpClient:
public void PostContainAttachment(string url, Dictionary<string, string> formFields, Dictionary<string, byte[]> attachments) { using (var httpClient = new HttpClient()) { if (attachments != null && attachments.Any()) { foreach (var item in attachments) { using (var content = new MultipartFormDataContent()) { using (var fileContent = new ByteArrayContent(item.Value)) { fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = item.Key, FileName = item.Key, FileNameStar = null }; content.Add(fileContent, "file"); //formFields是接口的传参 if (formFields != null) { foreach (string key in formFields.Keys) { content.Add(new StringContent(formFields[key]), "\"" + key + "\""); } } // 上传文件,获取返回的字符串内容 var result = httpClient.PostAsync(url, content).Result.Content.ReadAsStringAsync().Result; } } } attachments.Clear(); attachments = null; } } }