Nous avons la méthode UploadFile , mais il est limité à un seul fichier et ne nous permet pas de passer des paramètres supplémentaires. Alors allons-y et écrire de telle méthode. L’élément important est que cette méthode doit être conforme RFC 1867 afin que le serveur web distant peut analyser correctement les informations.
Tout d’abord, nous définissons un modèle représentant un seul fichier à télécharger :
public class UploadFile { public UploadFile() { ContentType = "application/octet-stream"; } public string Name { get; set; } public string Filename { get; set; } public string ContentType { get; set; } public Stream Stream { get; set; } }
Et voici une implémentation de la méthode sample UploadFiles :
public byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values) { var request = WebRequest.Create(address); request.Method = "POST"; var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo); request.ContentType = "multipart/form-data; boundary=" + boundary; boundary = "--" + boundary; using (var requestStream = request.GetRequestStream()) { // Write the values foreach (string name in values.Keys) { var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name="{0}"{1}{1}", name, Environment.NewLine)); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); } // Write the files foreach (var file in files) { var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name="{0}"; filename="{1}"{2}", file.Name, file.Filename, Environment.NewLine)); requestStream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType, Environment.NewLine)); requestStream.Write(buffer, 0, buffer.Length); file.Stream.CopyTo(requestStream); buffer = Encoding.ASCII.GetBytes(Environment.NewLine); requestStream.Write(buffer, 0, buffer.Length); } var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--"); requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length); } using (var response = request.GetResponse()) using (var responseStream = response.GetResponseStream()) using (var stream = new MemoryStream()) { responseStream.CopyTo(stream); return stream.ToArray(); } }
Et voici un exemple d’utilisation :
using (var stream1 = File.Open("test.txt", FileMode.Open)) using (var stream2 = File.Open("test.xml", FileMode.Open)) using (var stream3 = File.Open("test.pdf", FileMode.Open)) { var files = new[] { new UploadFile { Name = "file", Filename = "test.txt", ContentType = "text/plain", Stream = stream1 }, new UploadFile { Name = "file", Filename = "test.xml", ContentType = "text/xml", Stream = stream2 }, new UploadFile { Name = "file", Filename = "test.pdf", ContentType = "application/pdf", Stream = stream3 } }; var values = new NameValueCollection { { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }, }; byte[] result = UploadFiles("http://localhost:1234/upload", files, values); }
Dans cet exemple, nous sommes téléchargement 3 valeurs et 3 fichiers à l’hôte distant.
La prochaine fois, je vais montrer comment améliorer ce code en ajoutant une version asynchrone à l’aide de la bibliothèque TPL dans .NET 4.0.