通过HttpClient发布文件时,HttpRequest.Files为空

服务器端:

public HttpResponseMessage Post([FromUri]string machineName) { HttpResponseMessage result = null; var httpRequest = HttpContext.Current.Request; if (httpRequest.Files.Count > 0 && !String.IsNullOrEmpty(machineName)) ... 

客户端:

  public static void PostFile(string url, string filePath) { if (String.IsNullOrWhiteSpace(url) || String.IsNullOrWhiteSpace(filePath)) throw new ArgumentNullException(); if (!File.Exists(filePath)) throw new FileNotFoundException(); using (var handler = new HttpClientHandler { Credentials= new NetworkCredential(AppData.UserName, AppData.Password, AppCore.Domain) }) using (var client = new HttpClient(handler)) using (var content = new MultipartFormDataContent()) using (var ms = new MemoryStream(File.ReadAllBytes(filePath))) { var fileContent = new StreamContent(ms); fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = Path.GetFileName(filePath) }; content.Add(fileContent); content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); var result = client.PostAsync(url, content).Result; result.EnsureSuccessStatusCode(); } } 

在服务器端,httpRequest.Files集合始终为空。 但标题(内容长度等)是正确的。

您不应该使用HttpContext来获取ASP.NET Web API中的文件。 看看这个由Microsoft编写的示例( http://code.msdn.microsoft.com/ASPNET-Web-API-File-Upload-a8c0fb0d/sourcecode?fileId=67087&pathId=565875642 )。

 public class UploadController : ApiController { public async Task PostFile() { // Check if the request contains multipart/form-data. if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); try { StringBuilder sb = new StringBuilder(); // Holds the response body // Read the form data and return an async task. await Request.Content.ReadAsMultipartAsync(provider); // This illustrates how to get the form data. foreach (var key in provider.FormData.AllKeys) { foreach (var val in provider.FormData.GetValues(key)) { sb.Append(string.Format("{0}: {1}\n", key, val)); } } // This illustrates how to get the file names for uploaded files. foreach (var file in provider.FileData) { FileInfo fileInfo = new FileInfo(file.LocalFileName); sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length)); } return new HttpResponseMessage() { Content = new StringContent(sb.ToString()) }; } catch (System.Exception e) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); } } } 

试试这个方法:

  public void UploadFilesToRemoteUrl() { string[] files = { @"your file path" }; string url = "Your url"; long length = 0; string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url); httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary; httpWebRequest2.Method = "POST"; httpWebRequest2.KeepAlive = true; httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream memStream = new System.IO.MemoryStream(); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; memStream.Write(boundarybytes, 0, boundarybytes.Length); string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n"; for (int i = 0; i < files.Length; i++) { //string header = string.Format(headerTemplate, "file" + i, files[i]); string header = string.Format(headerTemplate, "uplTheFile", files[i]); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); memStream.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read); byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { memStream.Write(buffer, 0, bytesRead); } memStream.Write(boundarybytes, 0, boundarybytes.Length); fileStream.Close(); } httpWebRequest2.ContentLength = memStream.Length; Stream requestStream = httpWebRequest2.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.Close(); WebResponse webResponse2 = httpWebRequest2.GetResponse(); Stream stream2 = webResponse2.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); webResponse2.Close(); httpWebRequest2 = null; webResponse2 = null; } 

如果其他人有同样的问题:确保您的边界字符串有效,例如要这样做:

 using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture))) { ... } 

由于边界字符无效,可能是“/”日期分隔符,这对我来说失败了。 至少这解决了我在Nancy控制器(始终为空)中访问Context.Request.Files时的问题。

最好使用类似DateTime.Now.Ticks.ToString("x")东西。

除了应该是multipart/form-data的内容类型之外,代码中的一切看起来都很好。 请尝试更改代码以反映正确的内容类型:

 content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data"); 

您可能想要参考这篇文章,了解为什么将内容类型设置为application/octet-stream对客户端没有意义。