2009-06-05 7 views
2

Je travaille actuellement sur l'envoi d'un fichier d'une application C# à un hôte d'image (KalleLoad.net - avec le consentement des propriétaires, évidemment).La requête Web HTTP ne renvoie pas ce qui est attendu en C#

J'ai obtenu l'affichage réel de la demande de travailler, mais il ne retourne pas ce que je m'attendais. Le propriétaire du site de téléchargement m'a fourni une API (en quelque sorte) qui retournera du code XML avec les URL si je poste les données sur une certaine adresse. Je peux envoyer les données avec succès et obtenir une réponse du serveur, mais il renvoie simplement le code de la page d'accueil au lieu du code XML. Je ne peux pas comprendre pourquoi c'est ainsi.

J'ai également essayé de publier des données sur une simple page PHP sur mon serveur local et elle renvoie également le code de la page, au lieu de ce que j'ai demandé à la page de retourner sur le poste.

Voici l'intégralité de ma classe actuelle pour l'envoi des données. J'ai aussi comparé les en-têtes que j'ai envoyés depuis mon application avec ceux que firefox envoie depuis une demi-heure et je ne vois aucune différence entre les deux (d'après ce que j'en sais).

Toute aide à ce sujet serait fantastique et gracieusement reçu.

Cordialement, Andy Hunt

using System; 
using System.Net; 
using System.Text; 
using System.IO; 
using System.Collections; 
using System.Collections.Generic; 
using System.Drawing; 

namespace Skimpt_3._0 
{ 
    class PostFile 
    { 
     private Hashtable FormElements; 
     private HttpWebRequest Request; 
     private MemoryStream FileStream; 

     private string CONTENT_BOUNDARY = "---------------------------265001916915724"; 

     public string ContentMIMEType; 
     public string FormURL; 
     public string FileName; 
     public string Response; 
     public string FileBoxName; 

     //private int BufferSize; 

     public PostFile(string Url, string strFileName) 
     { 
      FormElements = new Hashtable(); 
      FormURL = Url; 
      Request = (HttpWebRequest)WebRequest.Create(Url); 
      //BufferSize = 10240; 
      FileStream = new MemoryStream(); 
      FileName = strFileName; 
     } 

     public void Send(Image image) 
     { 
      //Assign the request here too, just in case 
      Request = (HttpWebRequest)WebRequest.Create(FormURL); 

      Request.Method = "POST"; 
      Request.AllowWriteStreamBuffering = true; 
      Request.ProtocolVersion = HttpVersion.Version11; 
      Request.Headers.Add("Cache-Control", "no-cache"); 
      Request.KeepAlive = true; 
      Request.ContentType = "multipart/form-data; boundary=---------------------------265001916915724"; 
      StartFileStream(FileStream); 

      //Must be done in this order for stream to write properly: 
      //---- 
      //Form elements 
      //File header 
      //Image 
      //File trailer 
      //---- 
      WriteStringToStream(FileStream, GetFormElements()); 
      WriteImageToStream(FileStream, image, FileName); 

      CloseStream(FileStream); 


      byte[] FileByteArray = FileStream.ToArray(); 

      Request.ContentLength = FileByteArray.Length; 

      Stream PostingStream = Request.GetRequestStream(); 
      PostingStream.Write(FileByteArray, 0, FileByteArray.Length); 

      WebResponse resp = (HttpWebResponse)Request.GetResponse(); 

      StreamReader SR = new StreamReader(resp.GetResponseStream()); 

      PostingStream.Close(); 

      FileStream.Close(); 
      Request.GetRequestStream().Close(); 
      Response = SR.ReadToEnd(); 
      Request = null; 
     } 

     private void CloseStream(MemoryStream FileStream) 
     { 
      byte[] BytesToWrite = Encoding.ASCII.GetBytes(CONTENT_BOUNDARY); 
      FileStream.Write(BytesToWrite, 0, BytesToWrite.Length); 
     } 

     private void StartFileStream(MemoryStream FileStream) 
     { 
      // \r\n = new line 
      string str = "POST " + FormURL +"Content-Type: multipart/form-data; boundary="+CONTENT_BOUNDARY+" \r\n \r\n" + CONTENT_BOUNDARY; 
      byte[] BytesToWrite = Encoding.ASCII.GetBytes(str); 
      FileStream.Write(BytesToWrite, 0, BytesToWrite.Length); 
     } 

     private Byte[] ConvertImageToByteArray(Image img) 
     { 
      //Method taken from http://www.csharp-station.com/Articles/Thumbnails.aspx and adapted 
      MemoryStream memStream = new MemoryStream(); 
      img.Save(memStream, System.Drawing.Imaging.ImageFormat.Png); 

      byte[] byteArray = new Byte[memStream.Length]; 

      memStream.Position = 0; 
      memStream.Read(byteArray, 0, (int)memStream.Length); 
      return byteArray; 
     } 

     public void AddFormElement(string ElementName, string ElementValue) 
     { 
      FormElements[ElementName] = ElementValue; 
     } 

     private string GetFormElements() 
     { 
      string str = ""; 
      IDictionaryEnumerator myEnumerator = FormElements.GetEnumerator(); 
      while (myEnumerator.MoveNext()) 
      { 
       str += CONTENT_BOUNDARY + "\r\n" + 
        "Content-Disposition: form-data; name=" + myEnumerator.Key + 
        "\r\n\r\n" + 
        myEnumerator.Value +"\r\n"; 
      } 
      return str; 
     } 


     private void WriteStringToStream(System.IO.MemoryStream stream, string String) 
     { 
      byte[] PostData = System.Text.Encoding.ASCII.GetBytes(String); 
      stream.Write(PostData, 0, PostData.Length); 
     } 

     private void WriteImageToStream(System.IO.MemoryStream Stream, Image img, string FileName) 
     { 
      byte[] ByteArray = ConvertImageToByteArray(img); 
      string head = CONTENT_BOUNDARY + "\r\n" + 
          "Content-Disposition: form-data; name=\"" + FileBoxName + "\"; filename=\"" + FileName + "\"\r\n" + 
          "Content-Type: " + ContentMIMEType + "\r\n\r\n"; 
      byte[] header = Encoding.ASCII.GetBytes(head); 

      Stream.Write(header, 0, header.Length); 

      Stream.Write(ByteArray, 0, ByteArray.Length); 
     } 
    } 
} 
+0

Je suis en train de lire votre code en ce moment, et j'ai remarqué quelque chose qui n'est pas lié à la réponse web. Pour votre méthode de conversion de l'image en octet [], après avoir exécuté img.Save (....), vous pouvez simplement renvoyer memStream.ToArray(), ce qui retournera l'octet [] de votre image. – Aaron

+0

Merci, je l'ai réparé maintenant. Je ne vais pas déranger la mise à jour dans le code ci-dessus car il n'a pas vraiment besoin d'être mis à jour –

Répondre

1

D'après ce que je peux dire la requête POST que vous soumettez n'est pas formé correctement. Je ne pense pas que le serveur comprenne comment interpréter les données que vous envoyez (donc vous n'obtenez pas la réponse que vous attendez).

Quelle requête POST à ​​télécharger devrait ressembler

POST /_layouts/Upload.aspx HTTP/1.1 
Content-Type: multipart/form-data; boundary=---------------------------7d9192265018e 
Host: 127.0.0.1:25540 
Content-Length: 3573 
Connection: Keep-Alive 
---------------------------7d9192265018e 
-----------------------------7d9192265018e 
Content-Disposition: form-data; name="uploadFile"; filename="C:\Temp\TestDocument.txt" 
Content-Type: text/plain 

blah 
-----------------------------7d9192265018e-- 

(Remarque: la valeur Content-Length ci-dessus est faux. J'ai enlevé quelques trucs par souci de concision)


À quoi ressemble une demande POST que vous générez

POST /WebSite1/Default.aspx HTTP/1.1 
Cache-Control: no-cache 
Content-Type: multipart/form-data; boundary=---------------------------265001916915724 
Host: 127.0.0.1:25540 
Content-Length: 8626 
Expect: 100-continue 
Connection: Keep-Alive 

POST http://ipv4.fiddler:25540/WebSite1/Default.aspxContent-Type: multipart/form-data; boundary=-----------------------------265001916915724 

-----------------------------265001916915724-----------------------------265001916915724 
Content-Disposition: form-data; name=""; filename="Test.png" 
Content-Type: 

?PNG 
-----------------------------265001916915724-- 

(Remarque: J'ai omises les données de fichier PNG que je l'ai testé avec)


En comparant les deux, je peux voir les problèmes suivants:

  • La limite est utilisé incorrectement. Vous utilisez la même chaîne dans tous les endroits. Après avoir défini une valeur limite (exemple: boundary=aaaBBBcccDDDeee) à l'aide de l'en-tête Content-Type, utilisez la limite précédée de "-" (exemple: - boundary=aaaBBBcccDDDeee) pour délimiter chaque partie de votre soumission de formulaire en plusieurs parties. La limite finale marque la fin des données en plusieurs parties et doit être délimitée par un « - » préfixe et suffixe (exemple: --boundary=aaaBBBcccDDDeee-- Voir RFC 1341 (MIME): 7 pour plus d'infos
  • Il y a une tête Expect: 100-continue bizarre dans votre demande Cela ressemble... comme un problème avec la classe .NET HttpWebRequest et peut être désactivé.Voir HttpWebRequest and the Expect: 100-continue Header Problem pour plus d'informations.
  • La méthode StartFileStream essaie d'écrire une valeur d'en-tête mais vous la placez dans le corps de la demande. Il écrit également les en-têtes incorrectement. Je pense que cela devrait être entièrement omis (il semble que ce soit adapté d'un autre code de téléchargement). Le champ ContentMIMEType doit être défini sur le type MIME de l'image que vous téléchargez. Il n'est pas défini du tout, de sorte que le type de contenu: de l'image que vous téléchargez est vide. Idem pour le champ
  • Idem pour le champ FileBoxName.

Comment déboguer ce

Vous pouvez utiliser Fiddler pour voir la demande que votre envoi. Pour le configurer, vous devez pouvoir envoyer une requête à un serveur Web. Vous devriez être capable de l'exécuter et d'intercepter toute demande que vous essayez d'envoyer.

Ouf! C'était long. Bonne chance et j'espère que ça aide!

+0

Merci pour la réponse. Je vais aller voir toutes ces choses que tu as suggérées. En ce qui concerne les variables ContentMIMEType et FileBoxName, elles sont définies en dehors de la classe. IE Instance.ContentMIMEType = "image/png"; –

+0

Cela a fonctionné avec brio, merci. Il s'est avéré que tout ce dont j'avais besoin était d'ajouter les doubles tirets ("-") devant les limites du contenu à chaque fois. Encore une fois, merci beaucoup. Ça m'a dérangé pendant des jours. –

+0

Ok, cela fonctionne maintenant, mais seulement partiellement. Pour une raison quelconque, il télécharge, mais seulement partiellement. Il n'envoie pas le type MIME correctement ou la taille ou l'une de ces propriétés. Des idées? –

Questions connexes