2012-06-15 2 views
8

Я хочу загрузить файл на хост с помощью класса WebClient. Я также хочу передать некоторые значения, которые должны отображаться в массиве $ _POST на части сервера (PHP). Я хочу сделать это с помощью одного подключения нижеUploadFile с значениями POST от WebClient

using (WebClient wc = new WebClient()) 
{ 
    wc.Encoding = Encoding.UTF8; 
    NameValueCollection values = new NameValueCollection(); 
    values.Add("client", "VIP"); 
    values.Add("name", "John Doe"); 
    wc.QueryString = values; // this displayes in $_GET 
    byte[] ans= wc.UploadFile(address, dumpPath); 
} 

я использовал код Если я использовал свойство QueryString, отображенные в $ _GET array.But значения я хочу, чтобы отправить его методом пост

+0

Похожий вопрос здесь HTTP: // StackOverflow. com/questions/2950292/how-to-upload-multiple-files-using-webclient-uploadfile-uploadvalues-in-c Возможно, вы захотите проверить ответы –

ответ

30

Нет ничего встроенного, позволяющего это сделать. У меня есть blogged о расширении, которое вы могли бы использовать. Вот соответствующие классы:

public class UploadFile 
{ 
    public UploadFile() 
    { 
     ContentType = "application/octet-stream"; 
    } 
    public string Name { get; set; } 
    public string Filename { get; set; } 
    public string ContentType { get; set; } 
    public Stream Stream { get; set; } 
} 

public byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values) 
{ 
    var request = WebRequest.Create(address); 
    request.Method = "POST"; 
    var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo); 
    request.ContentType = "multipart/form-data; boundary=" + boundary; 
    boundary = "--" + boundary; 

    using (var requestStream = request.GetRequestStream()) 
    { 
     // Write the values 
     foreach (string name in values.Keys) 
     { 
      var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); 
      requestStream.Write(buffer, 0, buffer.Length); 
      buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine)); 
      requestStream.Write(buffer, 0, buffer.Length); 
      buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine); 
      requestStream.Write(buffer, 0, buffer.Length); 
     } 

     // Write the files 
     foreach (var file in files) 
     { 
      var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); 
      requestStream.Write(buffer, 0, buffer.Length); 
      buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine)); 
      requestStream.Write(buffer, 0, buffer.Length); 
      buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType, Environment.NewLine)); 
      requestStream.Write(buffer, 0, buffer.Length); 
      file.Stream.CopyTo(requestStream); 
      buffer = Encoding.ASCII.GetBytes(Environment.NewLine); 
      requestStream.Write(buffer, 0, buffer.Length); 
     } 

     var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--"); 
     requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length); 
    } 

    using (var response = request.GetResponse()) 
    using (var responseStream = response.GetResponseStream()) 
    using (var stream = new MemoryStream()) 
    { 
     responseStream.CopyTo(stream); 
     return stream.ToArray(); 
    } 
} 

и теперь вы можете использовать его в своем приложении:

using (var stream = File.Open(dumpPath, FileMode.Open)) 
{ 
    var files = new[] 
    { 
     new UploadFile 
     { 
      Name = "file", 
      Filename = Path.GetFileName(dumpPath), 
      ContentType = "text/plain", 
      Stream = stream 
     } 
    }; 

    var values = new NameValueCollection 
    { 
     { "client", "VIP" }, 
     { "name", "John Doe" }, 
    }; 

    byte[] result = UploadFiles(address, files, values); 
} 

Теперь в вашем PHP скрипт вы можете использовать $_POST["client"], $_POST["name"] и $_FILES["file"].

+0

, какими будут шаги для этого асинхронного вызова с индикацией прогресса? – Pbirkoff

+0

Синхронные функции на HttpWebClient должны быть заменены их асинхронными аналогами: Begin/EndGetRequestStream, Begin/EndGetResponse, ... –

+0

Благодарим вас за этот код! Если вы используете MVC 4, вы можете получить это исключение: «Неожиданный конец многопоточного потока MIME. MIME-сообщение не завершено. ' Внутри рамки есть ошибка (http://aspnetwebstack.codeplex.com/discussions/354215), и вам нужно добавить новую строку на последней границе: var borderBuffer = Encoding.ASCII.GetBytes (граница + "-" + Environment.NewLine); –

3

Если кто-то хочет использовать @ решение Дарин-Димитров сек в шаблоне асинхронном с отчетности прогресс, это путь (для .NET 4.0):

public void UploadFileAsync(NameValueCollection values, Stream fileStream) 
{ 
    //to fire events on the calling thread 
    _asyncOperation = AsyncOperationManager.CreateOperation(null); 
    var ms = new MemoryStream(); 
    //make a copy of the input stream in case sb uses disposable stream 
    fileStream.CopyTo(ms); 
    //you cannot set stream position often enough to zero 
    ms.Position = 0; 

    Task.Factory.StartNew(() => 
    { 
     try 
     { 
      const string contentType = "application/octet-stream"; 

      var request = WebRequest.Create(_url); 
      request.Method = "POST"; 
      var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo); 
      request.ContentType = "multipart/form-data; boundary=" + boundary; 
      boundary = "--" + boundary; 

      var dataStream = new MemoryStream(); 
      byte[] buffer; 
      // Write the values 
      foreach (string name in values.Keys) 
      { 
       buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); 
       dataStream.Write(buffer, 0, buffer.Length); 
       buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine)); 
       dataStream.Write(buffer, 0, buffer.Length); 
       buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine); 
       dataStream.Write(buffer, 0, buffer.Length); 
      } 

      // Write the file 
      buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); 
      dataStream.Write(buffer, 0, buffer.Length); 
      buffer = Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"file\"; filename=\"file\"{Environment.NewLine}"); 
      dataStream.Write(buffer, 0, buffer.Length); 
      buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", contentType, Environment.NewLine)); 
      dataStream.Write(buffer, 0, buffer.Length); 
      ms.CopyTo(dataStream); 
      buffer = Encoding.ASCII.GetBytes(Environment.NewLine); 
      dataStream.Write(buffer, 0, buffer.Length); 

      buffer = Encoding.ASCII.GetBytes(boundary + "--"); 
      dataStream.Write(buffer, 0, buffer.Length); 


      dataStream.Position = 0; 
      //IMPORTANT: set content length to directly write to network socket 
      request.ContentLength = dataStream.Length; 
      var requestStream = request.GetRequestStream(); 

      //Write data in chunks and report progress 
      var size = dataStream.Length; 
      const int chunkSize = 64 * 1024; 
      buffer = new byte[chunkSize]; 
      long bytesSent = 0; 
      int readBytes; 
      while ((readBytes = dataStream.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       requestStream.Write(buffer, 0, readBytes); 
       bytesSent += readBytes; 

       var status = "Uploading... " + bytesSent/1024 + "KB of " + size/1024 + "KB"; 
       var percentage = Tools.Clamp(Convert.ToInt32(100 * bytesSent/size), 0, 100); 
       OnFileUploaderProgressChanged(new FileUploaderProgessChangedEventArgs(status, percentage)); 
      } 

      //get response 
      using (var response = request.GetResponse()) 
      using (var responseStream = response.GetResponseStream()) 
      using (var stream = new MemoryStream()) 
      { 
       // ReSharper disable once PossibleNullReferenceException - exception would get catched anyway 
       responseStream.CopyTo(stream); 
       var result = Encoding.Default.GetString(stream.ToArray()); 
       OnFileUploaderCompleted(result == string.Empty 
        ? new FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Failed) 
        : new FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Ok)); 
      } 
     } 
     catch (Exception) 
     { 
      OnFileUploaderCompleted(new FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Failed)); 
     } 
    }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); 
} 
Смежные вопросы