2010-07-15 4 views
-1

J'ai besoin d'utiliser HttpWebClient pour télécharger une série de fichiers à la fois.C# .NET HttpWebClient ne peut pas faire fonctionner le téléchargement de fichiers; conseils de dépannage?

Je suivais l'exemple de code trouvé sur ce fil:

Upload files with HTTPWebrequest (multipart/form-data)

Comme plusieurs personnes ont rapporté sur ce fil, je suis également obtenir le statut HTTP 500 erreurs. J'ai essayé 2 des solutions proposées dans le fil, mais aucune ne fonctionne pour moi. Il semble qu'il y ait un problème lié à l'espacement dans la requête, mais je n'ai pas réussi à le comprendre.

Questions:

  1. Quelles sont les ressources dois-je utiliser pour vérifier que la requête HTTP est correctement formaté?

  2. Il devrait être possible d'écrire manuellement la requête si je copie et colle la section de fichier, non?

  3. Si vous connaissez un exemple de code qui fonctionne, s'il vous plaît faites le moi savoir.

Voici le code que j'utilise:

public static void UploadFilesToRemoteUrl(string url, string[] files, 
string logpath, NameValueCollection nvc) 
{ 

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

foreach (string key in nvc.Keys) 
{ 
    string formitem = string.Format(formdataTemplate, key, nvc[key]); 
    byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); 
    memStream.Write(formitembytes, 0, formitembytes.Length); 
} 


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


MessageBox.Show(reader2.ReadToEnd()); 

webResponse2.Close(); 
httpWebRequest2 = null; 
webResponse2 = null; 
} 

Mise à jour:

Merci à ck pour me encourager à continuer à utiliser Fiddler. C'était la direction dont j'avais besoin pour trouver la solution à ce problème.

Maintenant laissez-moi répondre aux questions ici.

1. Quelle ressource dois-je utiliser pour vérifier que la requête HTTP est formatée correctement? a) Les normes. Il existe RFC1867 http://www.faqs.org/rfcs/rfc1867.html. Bien lu. Il explique à qui le téléchargement multiple est censé se produire, ainsi que la manière dont vous gérez les autres données de formulaire. La limitation est que cela ne dit pas clairement comment la demande doit être formatée en termes de nombre de CRLF entre chaque en-tête et les valeurs. Je soupçonne que l'information peut être dans le HTTP RFC 2616 http://www.w3.org/Protocols/rfc2616/rfc2616.html mais c'est une lecture un peu plus longue pour le temps que j'avais. En outre, il peut y avoir une certaine marge d'interprétation entre différentes implémentations de celui-ci.

b) Exemples réels. La combinaison gagnante pour obtenir de vrais exemples utilisait curl et fiddler ensemble. J'ai été en mesure d'envoyer la demande de téléchargement correcte via curl, mais curl --trace-ascii ne me donnait pas l'en-tête brut dont j'avais besoin. Les approximations que j'ai faites à partir de ça ont échoué, et le violoniste n'a pas semblé capturer son trafic.

Puis j'ai trouvé un lien qui explique que curl n'utilise pas le proxy du système. Donc, pour capturer son trafic sur fiddler, il faut entrer curl -x 127.0.0.1:8888 www.happysmurfs.com Maintenant, j'ai l'en-tête brut dont j'avais besoin. MAINTENANT, avec l'en-tête brut correct, dépanner le code était facile, puisque j'avais un autre en-tête de texte pour le comparer avec lui.

2. Il devrait être possible d'écrire manuellement la requête si je copie et colle la section de fichier, non? Oui, il semble que ce soit possible, mais comme ck l'a mentionné, il est beaucoup plus facile d'obtenir un en-tête de fiddler qui fonctionne, et de faire des modifications à partir de là.

3. Si vous connaissez un exemple de code qui fonctionne, faites le moi savoir. Le code ci-dessus devrait fonctionner, mais attention à cette ligne:

string formdataTemplate = "\r\n--" + boundary + 
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; 

Le premier \ r \ n ne devrait pas être là. De même, il ne devrait pas y avoir de doubles nouvelles lignes, (\ r \ n), à la fin des en-têtes ou des limites.

Répondre

1

Vous devez utiliser Fiddler pour vérifier que l'envoi de votre programme est le même que celui que vous enverriez si vous le faites manuellement.

+0

Merci pour la réponse. J'utilise le violoneux. J'ai essayé de modifier la demande manuellement, mais elle échoue toujours. –

+0

Merci, ck. J'ai continué à travailler avec fiddler, et j'ai finalement trouvé un moyen d'obtenir la bonne demande brute. Je vous expliquerai dans une mise à jour un peu plus tard, une fois que je confirmerai mes hypothèses. –

+0

@Hugo - content de l'avoir fait fonctionner – cjk

Questions connexes