2013-03-21 2 views
5

стороны сервера:HttpRequest.Files пуст при отправке файла через HttpClient

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 коллекции всегда пусто. Но заголовки (длина контента и т. Д.) Являются правильными.

ответ

8

Вы не должны использовать 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); 
     } 
    } 

} 
+0

Почему мы не должны использовать 'HttpContext', когда' var postedFile = HttpContext.Current.Request.Files [0] ; 'просто дает опубликованный файл? Это прямо. – RBT

0

Попробуйте этот метод:

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

[Плагиат] (http://stackoverflow.com/questions/14874838/upload-pdf-with-parametrs-httpwebrequest)? –

+0

@Grant Thomas: Я также задаю тот же вопрос, и я изменил ответ, и я вставляю его здесь. http://stackoverflow.com/questions/15087028/upload-multiple-files-in-a-single-httpwebrequest – Popeye

0

В случае, если кто-то другой имеет такую ​​же проблему: убедитесь, что ваша граничная строка действительна, например. не это сделать:

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

Это не удалось, для меня из-за недопустимый пограничный характер, может быть «/» разделитель даты. По крайней мере, это решило мою проблему при доступе к Context.Request.Files в контроллере Nancy (который всегда был пустым).

Лучше использовать что-то наподобие DateTime.Now.Ticks.ToString("x").

0

Все выглядит хорошо в вашем коде, кроме типа контента, который должен быть multipart/form-data. Пожалуйста, попробуйте изменить код, чтобы отразить правильный тип контента:

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

Вы можете обратиться к this сообщению, почему настройки типа контента application/octet-stream не имеет смысла с клиентской стороны.

Смежные вопросы