【问题标题】:HttpRequest.Files is empty when posting file through HttpClient通过 HttpClient 发布文件时 HttpRequest.Files 为空
【发布时间】:2013-03-21 09:03:19
【问题描述】:

服务器端:

    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 集合总是空的。但是标题(内容长度等...)是正确的。

【问题讨论】:

    标签: c# .net asp.net-web-api httpclient


    【解决方案1】:

    您不应该使用 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<HttpResponseMessage> 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); 
            } 
        } 
    
    }
    

    【讨论】:

    • var postedFile = HttpContext.Current.Request.Files[0]; 只是给出发布的文件时,为什么我们不应该使用HttpContext?就是这么简单。
    【解决方案2】:

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

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

    您可能想参考this 帖子,了解为什么从客户端将内容类型设置为application/octet-stream 没有意义。

    【讨论】:

      【解决方案3】:

      试试这个方法:

          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;
          }
      

      【讨论】:

      【解决方案4】:

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

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

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

      最好改用DateTime.Now.Ticks.ToString("x") 之类的东西。

      【讨论】:

        猜你喜欢
        • 2017-12-17
        • 2011-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-21
        • 2013-06-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多