Transformer un form html en requete c#

Signaler
Messages postés
17
Date d'inscription
vendredi 28 mars 2003
Statut
Membre
Dernière intervention
31 octobre 2010
-
Messages postés
17
Date d'inscription
vendredi 28 mars 2003
Statut
Membre
Dernière intervention
31 octobre 2010
-
Bonjour je souhaiterai envoye par programme le resultat d'un form html
il s'agit de l'envoi de fax de free
qui peut m'aider a ecrire cette page en requete via du C#

<form class="form" method="post" action="tel_ulfax.pl" enctype="multipart/form-data" onsubmit="return checkForm ();">


Numéro du destinataire ,
,

----

Masquer le numéro appelant ,
,

----

Recevoir un rapport de transmission par e-mail ,
,

<!--tr>
Qualité "fine" ,
,

----

Fichier à envoyer ,

(PDF, JPG, DOC, XLS, TXT, ...),

----

<td colspan=\"2\" style=\"text-align:center\">


</form>
Eric

4 réponses

Messages postés
6063
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
27
Salut,

IL faut utiliser un client qui envoie des requete HTTP post

Par exemple
http://geekswithblogs.net/rakker/archive/2006/04/21/76044.aspx

bon dev.
Messages postés
17
Date d'inscription
vendredi 28 mars 2003
Statut
Membre
Dernière intervention
31 octobre 2010

Oui c'est ok j'ai reussi
Eric
Messages postés
6063
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
27
Tu pourrais poster un bout de solution pour les prochains qui se pose la question.
Messages postés
17
Date d'inscription
vendredi 28 mars 2003
Statut
Membre
Dernière intervention
31 octobre 2010

Bonjour voila ce que j'ai trouvé, deja poster dans un forum et ca marche

----------------------------------------------------------------

J'ai longuement cherché la facon de faire pour envoyer une requête POST qui inclut le contenu d'un fichier (content-type: multipart/form-data), mais sans succès, et c'est pourquoi j'ai donc du le créer moi même :-)

Le but est donc de simuler un formulaire d'une page web de ce type:

<form method="POST" action="http://site.com" enctype="multipart/form-data">




</form>


Comment ca marche?
J'utilise un HttpWebRequest pour créé la requête, puis j'y ajoute le contenu (que je forme avec une class que j'ai créé et que je vais partager ici) grâce à la méthode GetRequestStream du HttpWebRequest.

Pour former le contenu, il faut savoir quel champ du formulaire doit être envoyé. Si vous voulez "simuler" une page web existante, je vous conseil de "sniffer" votre requête envoyé par la page web en question (avec Ethereal par exemple, un programme simple d'emplois et gratuit: http://www.ethereal.com/)

Commencez la capture dans Ethereal puis envoyer votre fichier avec la page web. Une fois que c'est envoyé, arretez la capture et trouvez le flux TCP qui correspond à la communication qui vous intéresse (bouton droit et "follow TCP stream")

Ca donne un truc de ce genre:

POST / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
Accept: text/xml,application/xml,application/xhtml+xml,tex t/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encodin g: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Referer: http://imageshack.us/
Content-Type: multipart/form-data; boundary=---------------------------41184676334
Ho st: imageshack.us
Content-Length: 1517
Connection: Keep-Alive

-----------------------------411846763 34
Content-Disposition: form-data; name="uploadtype"

on
---------------------------- -41184676334
Content-Disposition: form-data; name="fileupload"; filename="Sans titre.JPG"
Content-Type: image/jpeg

[..... Contenu du fichier .....]
-----------------------------41184676334
Co ntent-Disposition: form-data; name="MAX_FILE_SIZE"

3145728
-------------------- ---------41184676334
Content-Disposition: form-data; name="refer"

http://site.com/
------------------- ----------41184676334
Content-Disposition: form-data; name="brand"


-----------------------------411846 76334
Content-Disposition: form-data; name="optsize"

320x320
-------------------------- ---41184676334--

Ici par exemple, si il y a les champs suivants (leur nom) avec leur valeurs respectives:
Champ "uploadtype", valeur "on"
Champ "fileupload", ici il s'agit d'un champ FILE, il y a donc le paramètre "filename", le paramètre "Content-Type: image/jpeg", et la valeur = [Contenu du fichier]]
Champ "MAX_FILE_SIZE", valeur "3145728"
Champ "refer", valeur "http://site.com/"
Champ "brand", valeur ""
Champ "optsize", valeur "320x320"

On ne sait pas de quel type sont le champ (TEXT, RADIO, CHECKBOX..) mais ce n'est pas important, sauf pour le champ FILE.



Cette classe à été créé selon mes besoins, et elle n'est pas capable de créer n'importe quelle requête. Notament le contenu du fichier (Content-Type:) est dans mon code fixé à "image/jpeg", donc je ne sais pas ce que ca donne si on envois autre chose.

En tout cas, dans mon cas ca fonctionne. Si vous avez d'autre type de champs à envoyer qui ne sont pas géré dans cette classe, ca vous permet tout de même d'avoir une base qui fonctionne.

Attention, le boundary est fixé à "-----------------768299458641184676334" dans mon code. Normalement il faut s'assurer que la chaine de caratères formant le boundary ne soit présente nul part ailleur dans les données à envoyer, car si c'est le cas, la requête échouera.

Le contenu du fichier est entièrement lu pour créer les données à envoyer, puis envoyé en 1 seul bloc. Cette méthode ne convient donc pas pour l'envois de gros fichiers, dans quel cas il faudrait découper le fichier en petites partie et les envoyer les une après les autres.

Voilà, c'est tout. J'espère que ce code sera utile à certains, car j'ai vu bcp de gens chercher à faire ca, mais très souvent sans avoir eu la réponse :-)


PS. Je ne donne pas de zip, car mon projet est nettement plus gros et j'utilise cette classe en multi-threading (dans un BackGroundWorker). J'ai juste retapé la procédure SendFile pour vous faire part de l'usage.http://www.vbfrance.com/codes/ENVOI-FICHIER-REQUETE-POST-MULTIPART-FORM-DATA-SIMLULATION_39802.aspx


' La requête se fait avec un HttpWebRequest, et on créé les données par la class que j'ai créé qui s'appel MultipartFormDataBodyCreator.
'
' Propriété et procédures publiques de MultipartFormDataBodyCreator:
'
' Public Sub Add(Name as String, _ ' Le nom du champs à ajouter
' Value as String, _ ' La valeur
' Optional IsFileField as Bollean False") ' Si il s'agit d'un fichier, mettre IsFileField true
' ' et Value = le chemin du fichier
'
' Public Property Boundary as String ' Le Boundary à utiliser (sert à délimiter les champs dans la requête)
'
' Public Function Create() as Byte() ' Retourne les données à envoyer sous forme d'un tableau de byte
'
'
' Pour envoyer la requête présenté juste au dessus, il faut donc faire comme ceci:


Private Sub SendFile()

Try

Dim bodyCreator As New MultipartFormDataBodyCreater ' La classe que j'ai créé et que je présente plus loins
Dim File as String = "C:\Image.jpg" ' Le fichier à envoyer

' Création des données à envoyer
' --------------------
bodyCreator.Fields.Add("uploadtype", "on")
bodyCreator.Fields.Add("fileupload", File, True) ' C'est le fichier
bodyCreator.Fields.Add("MAX_FILE_SIZE", "3145728")
bodyCreator.Fields.Add("refer", "http://site.com/")
bodyCreator.Fields.Add("brand", "")
bodyCreator.Fields.Add("optsize", "320x320")

Dim body() as Byte = bodyCreator.Create ' Les données à envoyer sous forme de tableau de Byte
Dim boundary as String = bodyCreater.Boundary ' Le boudary délimitant les champs. Utile pour créer la requête

' Création de la requête
' ------------------------
Dim Request as HttpWebRequest = HttpWebRequest.Create("http://site.com")
Request.Method = "POST"
Request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7"
Request.KeepAlive = True
Request.ServicePoint.Expect100Continue = False ' Important si le serveur ne gère pas les Expect
Request.Referer = "http://site.com/"
Request.ContentType = "multipart/form-data; boundary=" & boundary ' Ajouter le boundary après le Content-Type
Request.ContentLength = body.Length

' Ecriture des données
' ------------------------------------
Dim writer As Stream = Request.GetRequestStream
writer.Write(body, 0, body.Length)
writer.Close()

' Réponse
' -----------------
Dim response = Request.GetResponse()
Dim reader As New IO.StreamReader(response.GetResponseStream())
Dim ResponseBody = reader.ReadToEnd
reader.Close()
Response.Close()

Console.WriteLine(ResponseBody) ' Le réponse du serveur

Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub

Public Class MultipartFormDataBodyCreator

' Le Boundary délimitant chaque élément (Field) dans le corps du message
' On y met une valeure constante, mais normalement il faudrait s'assurer que cette
' chaine de caractère n'existe pas ailleur dans les données à envoyer (si c'est le cas, l'envois va planter)
Public Property Boundary() As String
Get
Return _Boundary
End Get
Set(ByVal value As String)
_Boundary = value
End Set
End Property
Private _Boundary As String = "-----------------768299458641184676334"

' Les éléments à inclure dans le corps du message, tous défini par une paire Nom/Valeur
' Une propriété IsFileField as Bollean définie si c'est le champs du fichier à envoyer
' (dans quel cas Value contiendra le chemin du fichier à envoyer)
Public Property Fields() As FieldList
Get
Return _Fields
End Get
Set(ByVal value As FieldList)
_Fields = value
End Set
End Property
Private _Fields As New FieldList

' Création d'un tableau de bytes contenant toutes les données à envoyer durant le request
Public Function Create() As Byte()

Dim encoding As New System.Text.ASCIIEncoding() ' Pour convertir le text en bytes
Dim body(-1) As Byte ' Le contenu final

' Parcourir tous les champs pour créer le body
For Each Field As Field In _Fields
Dim sb As New System.Text.StringBuilder ' Pour créer les champs texte
Dim FieldAsBytes() As Byte ' Le champs à ajouter au body en bytes

' Ajouter ce qui est commun aux champs FILE et les autres, c'est à dire une
' ligne avec le bundary puis la disposition et le nom du champ sur une autre ligne
sb.AppendLine("--" & Boundary) ' Le bundary précédé de "--"
sb.Append("Content-Disposition: form-data; name=""" & Field.Name & """") ' La disposition et le nom du champs (sans finir la ligne!)

' La suite dépend si c'est un fichier ou non
If Field.IsFileField Then ' C'est un fichier

' Ajouter le nom du fichier sur la meme ligne que le nom du champ
' Sur les lignes suivantes, le type de contenu et 1 ligne vide (puis viendra le fichier)
sb.AppendLine("; filename=""" & System.IO.Path.GetFileName(Field.Value) & """")
sb.AppendLine("Content-Type: image/jpeg" & vbCrLf)
FieldAsBytes = encoding.GetBytes(sb.ToString) ' Le 1er bout du champ codé en bytes

' On ajoute le contenu du fichier fichier au tableau FieldAsBytes
Dim FileBytes() As Byte = IO.File.ReadAllBytes(Field.Value) ' Le contenu du fichier
Array.Resize(FieldAsBytes, FieldAsBytes.Length + FileBytes.Length) ' Agrandir FieldAsBytes
Array.Copy(FileBytes, 0, FieldAsBytes, sb.Length, FileBytes.Length) ' Ajouter le contenu du fichier

' Ajouter un vbcrlf pour finir le champ
Array.Resize(FieldAsBytes, FieldAsBytes.Length + 2)
Array.Copy(encoding.GetBytes(vbCrLf), 0, FieldAsBytes, FieldAsBytes.Length - 2, 2)
Else

' C'est un élément du formulaire autre qu'un fichier
sb.AppendLine("") ' Finir la ligne précédente
sb.AppendLine(vbCrLf & Field.Value) ' Une ligne vide et la valeur
FieldAsBytes = encoding.GetBytes(sb.ToString) ' Créer un tableau de Byte

End If

' Ajouter la nouvelle entrée dans le body
Dim CurrentBodySize As Integer = body.Length
Array.Resize(body, body.Length + FieldAsBytes.Length) ' Agrandir le body
Array.Copy(FieldAsBytes, 0, body, body.Length - FieldAsBytes.Length, FieldAsBytes.Length) ' Copier FieldAsBytes à la fin du body
Next
' A la fin on ajoute le bundary et "--"
Dim EndLine() As Byte = encoding.GetBytes("--" & Boundary & "--" & vbCrLf)
Array.Resize(body, body.Length + EndLine.Length)
Array.Copy(EndLine, 0, body, body.Length - EndLine.Length, EndLine.Length)

Return body
End Function

End Class
Public Class FieldList
Inherits Generic.List(Of Field)

' Cette class éritée d'une collection générique List(Of Field) est créé juste pour ajouter les 2 procédures suivantes:
Public Overloads Sub Add(ByVal Name As String, ByVal Value As String, Optional ByVal IsFileField As Boolean = False)
MyBase.Add(New Field(Name, Value, IsFileField))
End Sub
Public Overloads Sub Insert(ByVal Index As Integer, ByVal Name As String, ByVal Value As String, Optional ByVal IsFileField As Boolean = False)
MyBase.Insert(Index, New Field(Name, Value, IsFileField))
End Sub
End Class
Public Class Field
' Représente un champs de formulaire
Public IsFileField As Boolean = False
Public Name As String = ""
Public Value As String = ""
Public Sub New()

End Sub
Public Sub New(ByVal Name As String, ByVal Value As String, Optional ByVal IsFileField As Boolean = False)
Me.Name = Name
Me.Value = Value
Me.IsFileField = IsFileField
End Sub
End Class




Traduction c# http://www.developerfusion.com/tools/convert/vb-to-csharp/

private void SendFile()
{

try {
MultipartFormDataBodyCreater bodyCreator = new MultipartFormDataBodyCreater();
// La classe que j'ai créé et que je présente plus loins
string File = "C:\\Image.jpg";
// Le fichier à envoyer

// Création des données à envoyer
// --------------------
bodyCreator.Fields.Add("uploadtype", "on");
bodyCreator.Fields.Add("fileupload", File, true);
// C'est le fichier
bodyCreator.Fields.Add("MAX_FILE_SIZE", "3145728");
bodyCreator.Fields.Add("refer", "http://site.com/");
bodyCreator.Fields.Add("brand", "");
bodyCreator.Fields.Add("optsize", "320x320");

byte[] body = bodyCreator.Create;
// Les données à envoyer sous forme de tableau de Byte
string boundary = bodyCreater.Boundary;
// Le boudary délimitant les champs. Utile pour créer la requête

// Création de la requête
// ------------------------
HttpWebRequest Request = HttpWebRequest.Create("http://site.com");
Request.Method = "POST";
Request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7";
Request.KeepAlive = true;
Request.ServicePoint.Expect100Continue = false;
// Important si le serveur ne gère pas les Expect
Request.Referer = "http://site.com/";
Request.ContentType = "multipart/form-data; boundary=" + boundary;
// Ajouter le boundary après le Content-Type
Request.ContentLength = body.Length;

// Ecriture des données
// ------------------------------------
Stream writer = Request.GetRequestStream;
writer.Write(body, 0, body.Length);
writer.Close();

// Réponse
// -----------------
dynamic response = Request.GetResponse();
System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());
dynamic ResponseBody = reader.ReadToEnd();
reader.Close();
response.Close();

Console.WriteLine(ResponseBody);
// Le réponse du serveur

} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
}

public class MultipartFormDataBodyCreator
{

// Le Boundary délimitant chaque élément (Field) dans le corps du message
// On y met une valeure constante, mais normalement il faudrait s'assurer que cette
// chaine de caractère n'existe pas ailleur dans les données à envoyer (si c'est le cas, l'envois va planter)
public string Boundary {
get { return _Boundary; }
set { _Boundary = value; }
}

private string _Boundary = "-----------------768299458641184676334";
// Les éléments à inclure dans le corps du message, tous défini par une paire Nom/Valeur
// Une propriété IsFileField as Bollean définie si c'est le champs du fichier à envoyer
// (dans quel cas Value contiendra le chemin du fichier à envoyer)
public FieldList Fields {
get { return _Fields; }
set { _Fields = value; }
}

private FieldList _Fields = new FieldList();
// Création d'un tableau de bytes contenant toutes les données à envoyer durant le request
public byte[] Create()
{

System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
// Pour convertir le text en bytes
byte[] body = new byte[-1 + 1];
// Le contenu final

// Parcourir tous les champs pour créer le body
foreach (Field Field in _Fields) {
System.Text.StringBuilder sb = new System.Text.StringBuilder();
// Pour créer les champs texte
byte[] FieldAsBytes = null;
// Le champs à ajouter au body en bytes

// Ajouter ce qui est commun aux champs FILE et les autres, c'est à dire une
// ligne avec le bundary puis la disposition et le nom du champ sur une autre ligne
sb.AppendLine("--" + Boundary);
// Le bundary précédé de "--"
sb.Append("Content-Disposition: form-data; name="" + Field.Name + """);
// La disposition et le nom du champs (sans finir la ligne!)

// La suite dépend si c'est un fichier ou non
// C'est un fichier
if (Field.IsFileField) {

// Ajouter le nom du fichier sur la meme ligne que le nom du champ
// Sur les lignes suivantes, le type de contenu et 1 ligne vide (puis viendra le fichier)
sb.AppendLine("; filename="" + System.IO.Path.GetFileName(Field.Value) + """);
sb.AppendLine("Content-Type: image/jpeg" + Constants.vbCrLf);
FieldAsBytes = encoding.GetBytes(sb.ToString());
// Le 1er bout du champ codé en bytes

// On ajoute le contenu du fichier fichier au tableau FieldAsBytes
byte[] FileBytes = System.IO.File.ReadAllBytes(Field.Value);
// Le contenu du fichier
Array.Resize(ref FieldAsBytes, FieldAsBytes.Length + FileBytes.Length);
// Agrandir FieldAsBytes
Array.Copy(FileBytes, 0, FieldAsBytes, sb.Length, FileBytes.Length);
// Ajouter le contenu du fichier

// Ajouter un vbcrlf pour finir le champ
Array.Resize(ref FieldAsBytes, FieldAsBytes.Length + 2);
Array.Copy(encoding.GetBytes(Constants.vbCrLf), 0, FieldAsBytes, FieldAsBytes.Length - 2, 2);

} else {
// C'est un élément du formulaire autre qu'un fichier
sb.AppendLine("");
// Finir la ligne précédente
sb.AppendLine(Constants.vbCrLf + Field.Value);
// Une ligne vide et la valeur
FieldAsBytes = encoding.GetBytes(sb.ToString());
// Créer un tableau de Byte

}

// Ajouter la nouvelle entrée dans le body
int CurrentBodySize = body.Length;
Array.Resize(ref body, body.Length + FieldAsBytes.Length);
// Agrandir le body
Array.Copy(FieldAsBytes, 0, body, body.Length - FieldAsBytes.Length, FieldAsBytes.Length);
// Copier FieldAsBytes à la fin du body
}
// A la fin on ajoute le bundary et "--"
byte[] EndLine = encoding.GetBytes("--" + Boundary + "--" + Constants.vbCrLf);
Array.Resize(ref body, body.Length + EndLine.Length);
Array.Copy(EndLine, 0, body, body.Length - EndLine.Length, EndLine.Length);

return body;
}

}
public class FieldList : Generic.List<Field>
{

// Cette class éritée d'une collection générique List(Of Field) est créé juste pour ajouter les 2 procédures suivantes:
public void Add(string Name, string Value, bool IsFileField = false)
{
base.Add(new Field(Name, Value, IsFileField));
}
public void Insert(int Index, string Name, string Value, bool IsFileField = false)
{
base.Insert(Index, new Field(Name, Value, IsFileField));
}
}
public class Field
{
// Représente un champs de formulaire
public bool IsFileField = false;
public string Name = "";
public string Value = "";

public Field()
{
}
public Field(string Name, string Value, bool IsFileField = false)
{
this.Name = Name;
this.Value = Value;
this.IsFileField = IsFileField;
}
}

Eric