2009-07-30 15 views
14

Qual è il modo più semplice per inviare una richiesta POST HTTP con un tipo di contenuto multipart/form-data da C#? Deve esserci un modo migliore di costruire la mia richiesta.Come inviare una richiesta POST HTTP multipart/form-data da C#

Il motivo che mi sto chiedendo è quello di caricare le foto su Flickr utilizzando questa API:

http://www.flickr.com/services/api/upload.api.html

+1

Ho cercato principalmente HttpWebRequest, ma ogni risorsa che ho trovato su Internet spiega come compilare manualmente la richiesta. Ecco uno dei tanti esempi simili che ho trovato: http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/03efc98c-68e2-410c-bf25-d5facacbd920 –

+0

Questa domanda ha una risposta che risolve il problema con la pubblicazione di dati multipart/form utilizzando WebRequest. Funziona bene. http://stackoverflow.com/questions/219827/multipart-forms-from-c-client – Marek

risposta

1

Prima di tutto, non c'è niente di sbagliato con la pura applicazione manuale dei comandi HTTP utilizzando il framework .Net. Tieni presente che è un framework e dovrebbe essere piuttosto generico.

In secondo luogo, penso che si possa provare a cercare un'implementazione del browser in .Net. Ho visto this one, forse copre il problema che hai chiesto. Oppure puoi semplicemente cercare "C# http put get post request". Uno dei risultati porta a una libreria non libera che può essere utile (Chilkat Http)

Se ti capita di scrivere il tuo framework di comandi HTTP su .Net - Penso che tutti noi possiamo godercelo se condividi :-)

+0

Purtroppo, questo è quello che dovevo fare. –

1

La classe System.Net.WebClient può essere ciò che stai cercando. Controllare la documentazione per WebClient.UploadFile, dovrebbe consentire di caricare un file in una risorsa specificata tramite uno dei sovraccarichi di UploadFile. Penso che questo sia il metodo che si sta cercando di utilizzare per inviare i dati ...

Può essere utilizzato come .... notare che questo è solo il codice di esempio non testato ...

WebClient WebClient = new WebClient();

webClient.UploadFile ("http://www.url.com/ReceiveUploadedFile.aspx", "POST", @ "c: \ myfile.txt");

Ecco il riferimento MSDN se sei interessato.

http://msdn.microsoft.com/en-us/library/system.net.webclient.uploadfile.aspx

Spero che questo aiuti.

+1

Funzionerebbe se volessi caricare il file. Tuttavia, ho bisogno di includere un mucchio di altre variabili di forma insieme ad esso. –

2

Ho avuto successo con il codice pubblicato a aspnetupload.com. Ho finito per creare la mia versione della libreria UploadHelper che è compatibile con Compact Framework. Funziona bene, sembra fare esattamente quello che ti serve.

+0

Dovrei aggiungere che "crea la mia versione" == prova a compilare la libreria in un progetto Compact Framework, guarda cosa c'è di rotto, usa un altro oggetto o segmento di codice compatibile con CF per fare la stessa cosa, ripeti. Sono rimasto piacevolmente sorpreso da quanto fosse semplice quel processo. –

5

Se si utilizza .NET 4.5 uso questo:

public string Upload(string url, NameValueCollection requestParameters, MemoryStream file) 
     { 

      var client = new HttpClient(); 
      var content = new MultipartFormDataContent(); 

      content.Add(new StreamContent(file)); 
      System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, string>> b = new List<KeyValuePair<string, string>>(); 
      b.Add(requestParameters); 
      var addMe = new FormUrlEncodedContent(b); 

      content.Add(addMe); 
      var result = client.PostAsync(url, content); 
      return result.Result.ToString(); 
     } 

Altrimenti Sulla base di risposta di Ryan, ho scaricato la biblioteca e ottimizzato un po '.

public class MimePart 
     { 
      NameValueCollection _headers = new NameValueCollection(); 
      byte[] _header; 

      public NameValueCollection Headers 
      { 
       get { return _headers; } 
      } 

      public byte[] Header 
      { 
       get { return _header; } 
      } 

      public long GenerateHeaderFooterData(string boundary) 
      { 
       StringBuilder sb = new StringBuilder(); 

       sb.Append("--"); 
       sb.Append(boundary); 
       sb.AppendLine(); 
       foreach (string key in _headers.AllKeys) 
       { 
        sb.Append(key); 
        sb.Append(": "); 
        sb.AppendLine(_headers[key]); 
       } 
       sb.AppendLine(); 

       _header = Encoding.UTF8.GetBytes(sb.ToString()); 

       return _header.Length + Data.Length + 2; 
      } 

      public Stream Data { get; set; } 
     } 

     public string Upload(string url, NameValueCollection requestParameters, params MemoryStream[] files) 
     { 
      using (WebClient req = new WebClient()) 
      { 
       List<MimePart> mimeParts = new List<MimePart>(); 

       try 
       { 
        foreach (string key in requestParameters.AllKeys) 
        { 
         MimePart part = new MimePart(); 

         part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\""; 
         part.Data = new MemoryStream(Encoding.UTF8.GetBytes(requestParameters[key])); 

         mimeParts.Add(part); 
        } 

        int nameIndex = 0; 

        foreach (MemoryStream file in files) 
        { 
         MimePart part = new MimePart(); 
         string fieldName = "file" + nameIndex++; 

         part.Headers["Content-Disposition"] = "form-data; name=\"" + fieldName + "\"; filename=\"" + fieldName + "\""; 
         part.Headers["Content-Type"] = "application/octet-stream"; 

         part.Data = file; 

         mimeParts.Add(part); 
        } 

        string boundary = "----------" + DateTime.Now.Ticks.ToString("x"); 
        req.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary); 

        long contentLength = 0; 

        byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n"); 

        foreach (MimePart part in mimeParts) 
        { 
         contentLength += part.GenerateHeaderFooterData(boundary); 
        } 

        //req.ContentLength = contentLength + _footer.Length; 

        byte[] buffer = new byte[8192]; 
        byte[] afterFile = Encoding.UTF8.GetBytes("\r\n"); 
        int read; 

        using (MemoryStream s = new MemoryStream()) 
        { 
         foreach (MimePart part in mimeParts) 
         { 
          s.Write(part.Header, 0, part.Header.Length); 

          while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0) 
           s.Write(buffer, 0, read); 

          part.Data.Dispose(); 

          s.Write(afterFile, 0, afterFile.Length); 
         } 

         s.Write(_footer, 0, _footer.Length); 
         byte[] responseBytes = req.UploadData(url, s.ToArray()); 
         string responseString = Encoding.UTF8.GetString(responseBytes); 
         return responseString; 
        } 
       } 
       catch 
       { 
        foreach (MimePart part in mimeParts) 
         if (part.Data != null) 
          part.Data.Dispose(); 

        throw; 
       } 
      } 
     } 
+1

La prima funzione non funziona. Cos'è "a"? – user656822

+0

Oops, avrebbe dovuto essere RequestParameters. Fisso. –

+0

So che è vecchio, ma non ha funzionato per me finché non ho inserito manualmente i miei contenuti come visto qui -> http://stackoverflow.com/a/12034014/885338 – Arikael

-1

io normalmente trovare Fiddler ad essere lo strumento migliore per quel lavoro. Molto facile creare richieste e persino generare alcune delle intestazioni per te.

Fiddler - How to create a request

enter image description here

2

Non ho provato io stesso, ma sembra che ci sia un modo incorporato in C# per questo (anche se non molto conosciuto uno a quanto pare ...):

private static HttpClient _client = null; 

private static void UploadDocument() 
{ 
    // Add test file 
    var httpContent = new MultipartFormDataContent(); 
    var fileContent = new ByteArrayContent(File.ReadAllBytes(@"File.jpg")); 
    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") 
    { 
     FileName = "File.jpg" 
    }; 

    httpContent.Add(fileContent); 
    string requestEndpoint = "api/Post"; 

    var response = _client.PostAsync(requestEndpoint, httpContent).Result; 

    if (response.IsSuccessStatusCode) 
    { 
     // ... 
    } 
    else 
    { 
     // Check response.StatusCode, response.ReasonPhrase 
    } 
} 

Provalo e fammi sapere come va.

Cheers!

Problemi correlati