2010-10-08 19 views
14

J'essaie d'utiliser l'API ImageShack pour télécharger des images. Pour l'utiliser, je suis censé POST l'image en utilisant multipart/form-data. Je l'ai fait ... aimeUtilisation de HttpWebRequest pour envoyer des données/envoyer une image en utilisant multipart/form-data

var postData = ""; 
var req = HttpWebRequest.Create("http://www.imageshack.us/upload_api.php"); 
req.Method = "POST"; 
req.ContentType = "multipart/form-data"; 
postData += "key=my_key_here&"; 
postData += "type=base64&"; 

// get base64 data from image 
byte[] bytes = File.ReadAllBytes(@"D:\tmp\WpfApplication1\WpfApplication1\Images\Icon128.gif"); 
string encoded = Convert.ToBase64String(bytes); 
postData += "fileupload=" + encoded; 

byte[] reqData = Encoding.UTF8.GetBytes(postData); 
using (Stream dataStream = req.GetRequestStream()) 
{ 
    dataStream.Write(reqData, 0, reqData.Length); 
} 

var res = (HttpWebResponse)req.GetResponse(); 
var resStream = res.GetResponseStream(); 
var reader = new StreamReader(resStream); 
string resString = reader.ReadToEnd(); 
txt1.Text = resString; 

mais ImageShack se plaint que

<links> 
    <error id="parameter_missing">Sorry, but we've detected that unexpected data is received. Required parameter 'fileupload' is missing or your post is not multipart/form-data</error> 
</links> 

FileUpload est présent et j'utilise multipart/form-data ce qui est erroné?

MISE À JOUR:

Nouveau Code http://pastebin.com/TN6e0CD8

données post http://pastebin.com/fYE9fsxs

MISE À JOUR 2

je regardais l'autre question Multipart forms from C# client. modifié mon code avec limite, retiré Expect 100 tête encore je ne peux pas le faire fonctionner ...

ServicePointManager.Expect100Continue = false; 
var boundary = "-----------------------------28520690214962"; 
var newLine = Environment.NewLine; 
var propFormat = boundary + newLine + 
        "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + 
        "{1}" + newLine + newLine; 
var fileHeaderFormat = boundary + newLine + 
         "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + newLine; 

var req = (HttpWebRequest)HttpWebRequest.Create("http://jm/php/upload.php"); 
req.Method = WebRequestMethods.Http.Post; 
req.ContentType = "multipart/form-data; boundary=" + boundary; 

using (var reqStream = req.GetRequestStream()) { 
    var reqWriter = new StreamWriter(reqStream); 
    var tmp = string.Format(propFormat, "str1", "hello world"); 
    reqWriter.Write(tmp); 
    tmp = string.Format(propFormat, "str2", "hello world 2"); 
    reqWriter.Write(tmp); 
    reqWriter.Write(boundary + "--"); 
    reqWriter.Flush(); 
} 
var res = req.GetResponse(); 
using (var resStream = res.GetResponseStream()) { 
    var reader = new StreamReader(resStream); 
    txt1.Text = reader.ReadToEnd(); 
} 
+1

double possible (http [Transférer des fichiers avec HttpWebRequest (multipart/form-data)]://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data) –

Répondre

11

Je crois que vous n'êtes pas la construction du corps de demande correctement. Tout d'abord, vous devez inclure la limite de partie (texte aléatoire) dans l'en-tête de type de contenu. Par exemple,

Type de contenu: multipart/form-data; boundary = ---- WebKitFormBoundarySkAQdHysJKel8YBM

maintenant le format du corps de la demande sera quelque chose comme

------WebKitFormBoundarySkAQdHysJKel8YBM 
Content-Disposition: form-data;name="key" 

KeyValueGoesHere 
------WebKitFormBoundarySkAQdHysJKel8YBM 
Content-Disposition: form-data;name="param2" 

ValueHere 
------WebKitFormBoundarySkAQdHysJKel8YBM 
Content-Disposition: form-data;name="fileUpload"; filename="y1.jpg" 
Content-Type: image/jpeg 

[image data goes here] 

Je vous suggère d'utiliser l'outil tels que Fiddler pour comprendre comment ces demandes sont construites.

+0

Je ne suis pas sûr si j'ai encore manqué quelque chose mais avec mes données de demande comme indiqué [@pastebin] (http: // code complet pastebin.com/vyqyG39A) également sur [pastebin] (http://pastebin.com/g1FDQnhH). Je reçois toujours la même erreur –

0

Ce ne ressemble en rien multipart/form-data

  1. Il n'y a pas de frontières entre les champs (nécessaires même avec un champ).
  2. Pourquoi êtes-vous encodage base-64?
  3. Il n'y a aucune indication sur le type de contenu de l'image. Jetez un oeil à RFC 2388 pour la spécification de format réelle.

Il peut également être utile de regarder un grappin Fiddler d'un téléchargement de fichier à partir d'une page Web.

+1

Oui, VinayC m'a mis en évidence cela. J'ai édité le code et il ressemble à [@pastebin] (http://pastebin.com/TN6e0CD8) maintenant. Et les données post générées ressemblent à ... [@pastebin] (http://pastebin.com/fYE9fsxs) –

+0

Les nouvelles lignes suivantes ne sont pas nécessaires après les valeurs. La base 64 est-elle une exigence spécifique à l'API? C'est inhabituel, mais je pouvais voir comment une API pourrait le demander. Comme la base-64 ne fait pas partie du format multiform, ce que vous envoyez n'est pas image/gif mais text/plain. Au-delà de cela, tant que les nouvelles lignes sont CRLF, il semble correct. Je recommande de ne pas terminer les noms de limites avec ----- car il est plus difficile de vérifier que le dernier est le même mais avec un supplément - –

+0

Comment renvoyer l'image? J'ai utilisé base64 après l'avoir vu utilisé quelque part. Alors peut-être que je le fais mal –

11

Je suis enfin avec le code suivant ...

var boundary = "------------------------" + DateTime.Now.Ticks; 
var newLine = Environment.NewLine; 
var propFormat = "--" + boundary + newLine + 
        "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + 
        "{1}" + newLine; 
var fileHeaderFormat = "--" + boundary + newLine + 
         "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + newLine; 

var req = (HttpWebRequest)HttpWebRequest.Create("http://jm/php/upload.php"); 
req.Method = WebRequestMethods.Http.Post; 
req.ContentType = "multipart/form-data; boundary=" + boundary; 

using (var reqStream = req.GetRequestStream()) { 
    var reqWriter = new StreamWriter(reqStream); 
    var tmp = string.Format(propFormat, "str1", "hello world"); 
    reqWriter.Write(tmp); 
    tmp = string.Format(propFormat, "str2", "hello world 2"); 
    reqWriter.Write(tmp); 
    reqWriter.Write("--" + boundary + "--"); 
    reqWriter.Flush(); 
} 
var res = req.GetResponse(); 
using (var resStream = res.GetResponseStream()) { 
    var reader = new StreamReader(resStream); 
    txt1.Text = reader.ReadToEnd(); 
} 

limites Remarque doivent commencer par -- {limite déclarée ContentType} et limite de fin doit commencer & fin avec --.dans mon cas, je l'origine utilisé

var propFormat = boundary + newLine + 
        "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + 
        "{1}" + newLine; 

le remplacer par

var propFormat = "--" + boundary + newLine + 
        "Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine + 
        "{1}" + newLine; 

et tout fonctionne

+0

C'était vraiment utile .. spécialement je ne donnais pas le nom du fichier ... – Barun

+2

Je ne sais pas voyez où vous utilisez 'fileHeaderFormat' ou où vous ajoutez le contenu du fichier. Pouvez-vous ajouter cela aussi? –

+0

requestWriter.Write (string.Format (fileHeaderFormat, "image", myImage.FileName, myImage.ContentType)); requestWriter.Flush(); requestStream.Write (myImageAsByteArray, 0, (myImageAsByteArray.Length); Ainsi, vous écrivez des chaînes à la demande avec requestWriter, mais écrivez simplement votre byte [] directement. –