Télécharger des fichiers avec HTTPWebrequest (multipart / form-data)

Y a-t-il une classe, une bibliothèque ou un morceau de code qui m’aidera à télécharger des fichiers avec HTTPWebrequest ?

Edit 2:

Je ne veux pas télécharger dans un dossier WebDAV ou quelque chose comme ça. Je veux simuler un navigateur, tout comme vous téléchargez votre avatar sur un forum ou téléchargez un fichier via un formulaire dans une application Web. Télécharger dans un formulaire qui utilise un multipart / form-data.

Modifier:

WebClient ne couvre pas mes besoins, alors je recherche une solution avec HTTPWebrequest .

Pris le code ci-dessus et corrigé car il jette une erreur interne au serveur 500. Il y a quelques problèmes avec \ r \ n mal placés et les espaces, etc. Voici le résultat:

public static void HttpUploadFile(ssortingng url, ssortingng file, ssortingng paramName, ssortingng contentType, NameValueCollection nvc) { log.Debug(ssortingng.Format("Uploading {0} to {1}", file, url)); ssortingng boundary = "---------------------------" + DateTime.Now.Ticks.ToSsortingng("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.KeepAlive = true; wr.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream rs = wr.GetRequestStream(); ssortingng formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (ssortingng key in nvc.Keys) { rs.Write(boundarybytes, 0, boundarybytes.Length); ssortingng formitem = ssortingng.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); rs.Write(formitembytes, 0, formitembytes.Length); } rs.Write(boundarybytes, 0, boundarybytes.Length); ssortingng headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; ssortingng header = ssortingng.Format(headerTemplate, paramName, file, contentType); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[4096]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { rs.Write(buffer, 0, bytesRead); } fileStream.Close(); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); rs.Write(trailer, 0, trailer.Length); rs.Close(); WebResponse wresp = null; try { wresp = wr.GetResponse(); Stream stream2 = wresp.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); log.Debug(ssortingng.Format("File uploaded, server response is: {0}", reader2.ReadToEnd())); } catch(Exception ex) { log.Error("Error uploading file", ex); if(wresp != null) { wresp.Close(); wresp = null; } } finally { wr = null; } } 

et exemple d’utilisation:

  NameValueCollection nvc = new NameValueCollection(); nvc.Add("id", "TTR"); nvc.Add("btn-submit-photo", "Upload"); HttpUploadFile("http://your.server.com/upload", @"C:\test\test.jpg", "file", "image/jpeg", nvc); 

Il pourrait être étendu pour gérer plusieurs fichiers ou simplement l’appeler plusieurs fois pour chaque fichier. Cependant, il convient à vos besoins.

Je cherchais quelque chose comme ceci, trouvé dans: http://bytes.com/groups/net-c/268661-how-upload-file-via-c-code (modifié pour l’exactitude):

 public static ssortingng UploadFilesToRemoteUrl(ssortingng url, ssortingng[] files, NameValueCollection formFields = null) { ssortingng boundary = "----------------------------" + DateTime.Now.Ticks.ToSsortingng("x"); HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; Stream memStream = new System.IO.MemoryStream(); var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--"); ssortingng formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; if (formFields != null) { foreach (ssortingng key in formFields.Keys) { ssortingng formitem = ssortingng.Format(formdataTemplate, key, formFields[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); memStream.Write(formitembytes, 0, formitembytes.Length); } } ssortingng 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++) { memStream.Write(boundarybytes, 0, boundarybytes.Length); var header = string.Format(headerTemplate, "uplTheFile", files[i]); var headerbytes = System.Text.Encoding.UTF8.GetBytes(header); memStream.Write(headerbytes, 0, headerbytes.Length); using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read)) { var buffer = new byte[1024]; var bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { memStream.Write(buffer, 0, bytesRead); } } } memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); request.ContentLength = memStream.Length; using (Stream requestStream = request.GetRequestStream()) { memStream.Position = 0; byte[] tempBuffer = new byte[memStream.Length]; memStream.Read(tempBuffer, 0, tempBuffer.Length); memStream.Close(); requestStream.Write(tempBuffer, 0, tempBuffer.Length); } using (var response = request.GetResponse()) { Stream stream2 = response.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); return reader2.ReadToEnd(); } } 

MISE À JOUR: En utilisant .NET 4.5 (ou .NET 4.0 en ajoutant le package Microsoft.Net.Http à partir de NuGet), cela est possible sans code externe, extensions et manipulation HTTP “bas niveau”. Voici un exemple:

 // Perform the equivalent of posting a form with a filename and two files, in HTML: // 
// // // //
private async Task UploadAsync(ssortingng url, ssortingng filename, Stream fileStream, byte [] fileBytes) { // Convert each of the three inputs into HttpContent objects HttpContent ssortingngContent = new SsortingngContent(filename); // examples of converting both Stream and byte [] to HttpContent objects // representing input type file HttpContent fileStreamContent = new StreamContent(fileStream); HttpContent bytesContent = new ByteArrayContent(fileBytes); // Submit the form using HttpClient and // create form data as Multipart (enctype="multipart/form-data") using (var client = new HttpClient()) using (var formData = new MultipartFormDataContent()) { // Add the HttpContent objects to the form data // formData.Add(ssortingngContent, "filename", "filename"); // formData.Add(fileStreamContent, "file1", "file1"); // formData.Add(bytesContent, "file2", "file2"); // Invoke the request to the server // equivalent to pressing the submit button on // a form with atsortingbutes (action="{url}" method="post") var response = await client.PostAsync(url, formData); // ensure the request was a success if (!response.IsSuccessStatusCode) { return null; } return await response.Content.ReadAsStreamAsync(); } }

Mon FAQ de téléchargement ASP.NET contient un article à ce sujet, avec un exemple de code: Télécharger des fichiers à l’aide d’une requête POST RFC 1867 avec HttpWebRequest / WebClient . Ce code ne charge pas les fichiers en mémoire (contrairement au code ci-dessus), prend en charge plusieurs fichiers et prend en charge les valeurs de formulaire, la définition des informations d’identification et des cookies, etc.

Edit: on dirait qu’Axosoft a pris la page. Merci les gars.

Il est toujours accessible via archive.org.

Basé sur le code fourni ci-dessus, j’ai ajouté le support de plusieurs fichiers et aussi télécharger directement un stream sans avoir besoin d’un fichier local.

Pour télécharger des fichiers vers une URL spécifique, y compris des parameters de publication, procédez comme suit:

 RequestHelper.PostMultipart( "http://soffr.miximages.com/.net/upload.php, new Dictionarystring, object() { { testparam, my value }, { file, new FormFile() { Name = image.jpg", ContentType = "image/jpeg", FilePath = "c:\\temp\\myniceimage.jpg" } }, { "other_file", new FormFile() { Name = "image2.jpg", ContentType = "image/jpeg", Stream = imageDataStream } }, }); 

Pour améliorer cela encore plus on pourrait déterminer le nom et le type MIME du fichier lui-même.

 public class FormFile { public ssortingng Name { get; set; } public ssortingng ContentType { get; set; } public ssortingng FilePath { get; set; } public Stream Stream { get; set; } } public class RequestHelper { public static ssortingng PostMultipart(ssortingng url, Dictionary parameters) { ssortingng boundary = "---------------------------" + DateTime.Now.Ticks.ToSsortingng("x"); byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; request.Credentials = System.Net.CredentialCache.DefaultCredentials; if(parameters != null && parameters.Count > 0) { using(Stream requestStream = request.GetRequestStream()) { foreach(KeyValuePair pair in parameters) { requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); if(pair.Value is FormFile) { FormFile file = pair.Value as FormFile; ssortingng header = "Content-Disposition: form-data; name=\"" + pair.Key + "\"; filename=\"" + file.Name + "\"\r\nContent-Type: " + file.ContentType + "\r\n\r\n"; byte[] bytes = System.Text.Encoding.UTF8.GetBytes(header); requestStream.Write(bytes, 0, bytes.Length); byte[] buffer = new byte[32768]; int bytesRead; if(file.Stream == null) { // upload from file using(FileStream fileStream = File.OpenRead(file.FilePath)) { while((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) requestStream.Write(buffer, 0, bytesRead); fileStream.Close(); } } else { // upload from given stream while((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0) requestStream.Write(buffer, 0, bytesRead); } } else { ssortingng data = "Content-Disposition: form-data; name=\"" + pair.Key + "\"\r\n\r\n" + pair.Value; byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data); requestStream.Write(bytes, 0, bytes.Length); } } byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); requestStream.Write(trailer, 0, trailer.Length); requestStream.Close(); } } using(WebResponse response = request.GetResponse()) { using(Stream responseStream = response.GetResponseStream()) using(StreamReader reader = new StreamReader(responseStream)) return reader.ReadToEnd(); } } } 

quelque chose comme ceci est proche: (code non testé)

 byte[] data; // data goes here. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Credentials = userNetworkCredentials; request.Method = "PUT"; request.ContentType = "application/octet-stream"; request.ContentLength = data.Length; Stream stream = request.GetRequestStream(); stream.Write(data,0,data.Length); stream.Close(); response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); temp = reader.ReadToEnd(); reader.Close(); 

A pris ce qui précède et modifié il accepte certaines valeurs d’en-tête et plusieurs fichiers

  NameValueCollection headers = new NameValueCollection(); headers.Add("Cookie", "name=value;"); headers.Add("Referer", "http://google.com"); NameValueCollection nvc = new NameValueCollection(); nvc.Add("name", "value"); HttpUploadFile(url, new ssortingng[] { "c:\\file1.txt", "c:\\file2.jpg" }, new ssortingng[] { "file", "image" }, new ssortingng[] { "application/octet-stream", "image/jpeg" }, nvc, headers); 

 public static void HttpUploadFile(ssortingng url, ssortingng[] file, ssortingng[] paramName, ssortingng[] contentType, NameValueCollection nvc, NameValueCollection headerItems) { //log.Debug(ssortingng.Format("Uploading {0} to {1}", file, url)); ssortingng boundary = "---------------------------" + DateTime.Now.Ticks.ToSsortingng("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); foreach (ssortingng key in headerItems.Keys) { if (key == "Referer") { wr.Referer = headerItems[key]; } else { wr.Headers.Add(key, headerItems[key]); } } wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.KeepAlive = true; wr.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream rs = wr.GetRequestStream(); ssortingng formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (ssortingng key in nvc.Keys) { rs.Write(boundarybytes, 0, boundarybytes.Length); ssortingng formitem = ssortingng.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); rs.Write(formitembytes, 0, formitembytes.Length); } rs.Write(boundarybytes, 0, boundarybytes.Length); ssortingng headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; ssortingng header = ""; for(int i =0; i 

Je pense que vous cherchez quelque chose de plus comme WebClient .

Plus précisément, UploadFile () .

Exemple VB (converti de l’exemple C # sur un autre poste):

 Private Sub HttpUploadFile( _ ByVal uri As Ssortingng, _ ByVal filePath As Ssortingng, _ ByVal fileParameterName As Ssortingng, _ ByVal contentType As Ssortingng, _ ByVal otherParameters As Specialized.NameValueCollection) Dim boundary As Ssortingng = "---------------------------" & DateTime.Now.Ticks.ToSsortingng("x") Dim newLine As Ssortingng = System.Environment.NewLine Dim boundaryBytes As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" & boundary & newLine) Dim request As Net.HttpWebRequest = Net.WebRequest.Create(uri) request.ContentType = "multipart/form-data; boundary=" & boundary request.Method = "POST" request.KeepAlive = True request.Credentials = Net.CredentialCache.DefaultCredentials Using requestStream As IO.Stream = request.GetRequestStream() Dim formDataTemplate As Ssortingng = "Content-Disposition: form-data; name=""{0}""{1}{1}{2}" For Each key As Ssortingng In otherParameters.Keys requestStream.Write(boundaryBytes, 0, boundaryBytes.Length) Dim formItem As Ssortingng = Ssortingng.Format(formDataTemplate, key, newLine, otherParameters(key)) Dim formItemBytes As Byte() = Text.Encoding.UTF8.GetBytes(formItem) requestStream.Write(formItemBytes, 0, formItemBytes.Length) Next key requestStream.Write(boundaryBytes, 0, boundaryBytes.Length) Dim headerTemplate As Ssortingng = "Content-Disposition: form-data; name=""{0}""; filename=""{1}""{2}Content-Type: {3}{2}{2}" Dim header As Ssortingng = Ssortingng.Format(headerTemplate, fileParameterName, filePath, newLine, contentType) Dim headerBytes As Byte() = Text.Encoding.UTF8.GetBytes(header) requestStream.Write(headerBytes, 0, headerBytes.Length) Using fileStream As New IO.FileStream(filePath, IO.FileMode.Open, IO.FileAccess.Read) Dim buffer(4096) As Byte Dim bytesRead As Int32 = fileStream.Read(buffer, 0, buffer.Length) Do While (bytesRead > 0) requestStream.Write(buffer, 0, bytesRead) bytesRead = fileStream.Read(buffer, 0, buffer.Length) Loop End Using Dim trailer As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" + boundary + "--" & newLine) requestStream.Write(trailer, 0, trailer.Length) End Using Dim response As Net.WebResponse = Nothing Try response = request.GetResponse() Using responseStream As IO.Stream = response.GetResponseStream() Using responseReader As New IO.StreamReader(responseStream) Dim responseText = responseReader.ReadToEnd() Diagnostics.Debug.Write(responseText) End Using End Using Catch exception As Net.WebException response = exception.Response If (response IsNot Nothing) Then Using reader As New IO.StreamReader(response.GetResponseStream()) Dim responseText = reader.ReadToEnd() Diagnostics.Debug.Write(responseText) End Using response.Close() End If Finally request = Nothing End Try End Sub 

J’ai dû gérer cela récemment – une autre façon de s’en approcher est d’utiliser le fait que WebClient est héritable, et de modifier le WebRequest sous-jacent à partir de là:

http://msdn.microsoft.com/en-us/library/system.net.webclient.getwebrequest(VS.80).aspx

Je préfère C #, mais si vous êtes bloqué avec VB, les résultats ressembleront à ceci:

 Public Class BigWebClient Inherits WebClient Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest Dim x As WebRequest = MyBase.GetWebRequest(address) x.Timeout = 60 * 60 * 1000 Return x End Function End Class 'Use BigWebClient here instead of WebClient 

Il y a un autre exemple de travail avec quelques commentaires:

  List mimeParts = new List(); try { foreach (ssortingng key in form.AllKeys) { SsortingngMimePart part = new SsortingngMimePart(); part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\""; part.SsortingngData = form[key]; mimeParts.Add(part); } int nameIndex = 0; foreach (UploadFile file in files) { StreamMimePart part = new StreamMimePart(); if (ssortingng.IsNullOrEmpty(file.FieldName)) file.FieldName = "file" + nameIndex++; part.Headers["Content-Disposition"] = "form-data; name=\"" + file.FieldName + "\"; filename=\"" + file.FileName + "\""; part.Headers["Content-Type"] = file.ContentType; part.SetStream(file.Data); mimeParts.Add(part); } ssortingng boundary = "----------" + DateTime.Now.Ticks.ToSsortingng("x"); req.ContentType = "multipart/form-data; boundary=" + boundary; req.Method = "POST"; long contentLength = 0; byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n"); foreach (MimePart part in mimeParts) { contentLength += part.GenerateHeaderFooterData(boundary); } req.ContentLength = contentLength + _footer.Length; byte[] buffer = new byte[8192]; byte[] afterFile = Encoding.UTF8.GetBytes("\r\n"); int read; using (Stream s = req.GetRequestStream()) { foreach (MimePart part in mimeParts) { s.Write(part.Header, 0, part.Header.Length); while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0) s.Write(buffer, 0, read); part.Data.Dispose(); s.Write(afterFile, 0, afterFile.Length); } s.Write(_footer, 0, _footer.Length); } return (HttpWebResponse)req.GetResponse(); } catch { foreach (MimePart part in mimeParts) if (part.Data != null) part.Data.Dispose(); throw; } 

Et il y a un exemple d’utilisation:

  UploadFile[] files = new UploadFile[] { new UploadFile(@"C:\2.jpg","new_file","image/jpeg") //new_file is id of upload field }; NameValueCollection form = new NameValueCollection(); form["id_hidden_input"] = "value_hidden_inpu"; //there is additional param (hidden fields on page) HttpWebRequest req = (HttpWebRequest)WebRequest.Create(full URL of action); // set credentials/cookies etc. req.CookieContainer = hrm.CookieContainer; //hrm is my class. i copied all cookies from last request to current (for auth) HttpWebResponse resp = HttpUploadHelper.Upload(req, files, form); using (Stream s = resp.GetResponseStream()) using (StreamReader sr = new StreamReader(s)) { ssortingng response = sr.ReadToEnd(); } //profit! 

Je cherchais à télécharger des fichiers et à append des parameters à une requête multipart / form-data dans VB.NET et non à une publication de formulaires standard. Grâce à @JoshCodes, j’ai obtenu la direction que je recherchais. Je poste ma solution pour aider les autres à trouver un moyen d’effectuer un post avec à la fois le fichier et les parameters. L’équivalent HTML de ce que j’essaie de réaliser est: html

 

Étant donné que je dois fournir l’apiKey et la signature (qui est une sum de contrôle calculée des parameters de la demande et de la chaîne concaténée de la clé API), je devais le faire côté serveur. L’autre raison pour laquelle je devais le faire côté serveur est le fait que la publication du fichier peut être effectuée à tout moment en pointant sur un fichier déjà présent sur le serveur (fournissant le chemin d’access). poster ainsi le fichier de données de formulaire ne contiendrait pas le stream de fichiers. Sinon, j’aurais pu calculer la sum de contrôle via un rappel ajax et soumettre le fichier via la publication html en utilisant JQuery. J’utilise .net version 4.0 et je ne peux pas passer à la version 4.5 de la solution actuelle. Je devais donc installer Microsoft.Net.Http en utilisant nuget cmd

 PM> install-package Microsoft.Net.Http Private Function UploadFile(req As ApiRequest, filePath As Ssortingng, fileName As Ssortingng) As Ssortingng Dim result = Ssortingng.empty Try ''//Get file stream Dim paramFileStream As Stream = File.OpenRead(filePath) Dim fileStreamContent As HttpContent = New StreamContent(paramFileStream) Using client = New HttpClient() Using formData = New MultipartFormDataContent() ''// This adds parameter name ("action") ''// parameter value (req.Action) to form data formData.Add(New SsortingngContent(req.Action), "action") formData.Add(New SsortingngContent(req.ApiKey), "apiKey") For Each param In req.Parameters formData.Add(New SsortingngContent(param.Value), param.Key) Next formData.Add(New SsortingngContent(req.getRequestSignature.Qualifier), "signature") ''//This adds the file stream and file info to form data formData.Add(fileStreamContent, "file", fileName) ''//We are now sending the request Dim response = client.PostAsync(GetAPIEndpoint(), formData).Result ''//We are here reading the response Dim readR = New StreamReader(response.Content.ReadAsStreamAsync().Result, Encoding.UTF8) Dim respContent = readR.ReadToEnd() If Not response.IsSuccessStatusCode Then result = "Request Failed : Code = " & response.StatusCode & "Reason = " & response.ReasonPhrase & "Message = " & respContent End If result.Value = respContent End Using End Using Catch ex As Exception result = "An error occurred : " & ex.Message End Try Return result End Function 

Je ne suis pas sûr que cela ait été posté avant, mais je travaille avec WebClient. J’ai lu la documentation du WebClient. Un point clé qu’ils font est

Si la propriété BaseAddress n’est pas une chaîne vide (“”) et que l’adresse ne contient pas d’URI absolu, l’adresse doit être un URI relatif associé à BaseAddress pour former l’URI absolu des données demandées. Si la propriété QuerySsortingng n’est pas une chaîne vide, elle est ajoutée à l’adresse.

Donc, tout ce que j’ai fait, c’est wc.QuerySsortingng.Add (“source”, generateImage) pour append les différents parameters de requête et, d’une manière ou d’une autre, il correspond au nom de la propriété avec l’image téléchargée. J’espère que cela aide

  public void postImageToFacebook(ssortingng generatedImage, ssortingng fbGraphUrl) { WebClient wc = new WebClient(); byte[] bytes = System.IO.File.ReadAllBytes(generatedImage); wc.QuerySsortingng.Add("source", generatedImage); wc.QuerySsortingng.Add("message", "helloworld"); wc.UploadFile(fbGraphUrl, generatedImage); wc.Dispose(); } 

Modification du code @CristianRomanescu pour travailler avec le stream de mémoire, accepter le fichier en tant que tableau d’octets, autoriser la valeur null nvc, renvoyer la réponse à la demande et utiliser l’en-tête d’autorisation. Testé le code avec Web Api 2.

 private ssortingng HttpUploadFile(ssortingng url, byte[] file, ssortingng fileName, ssortingng paramName, ssortingng contentType, NameValueCollection nvc, ssortingng authorizationHeader) { ssortingng boundary = "---------------------------" + DateTime.Now.Ticks.ToSsortingng("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.Headers.Add("Authorization", authorizationHeader); wr.KeepAlive = true; Stream rs = wr.GetRequestStream(); ssortingng formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; if (nvc != null) { foreach (ssortingng key in nvc.Keys) { rs.Write(boundarybytes, 0, boundarybytes.Length); ssortingng formitem = ssortingng.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); rs.Write(formitembytes, 0, formitembytes.Length); } } rs.Write(boundarybytes, 0, boundarybytes.Length); ssortingng headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; ssortingng header = ssortingng.Format(headerTemplate, paramName, fileName, contentType); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); rs.Write(file, 0, file.Length); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); rs.Write(trailer, 0, trailer.Length); rs.Close(); WebResponse wresp = null; try { wresp = wr.GetResponse(); Stream stream2 = wresp.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); var response = reader2.ReadToEnd(); return response; } catch (Exception ex) { if (wresp != null) { wresp.Close(); wresp = null; } return null; } finally { wr = null; } } 

Testcode:

 [HttpPost] [Route("postformdata")] public IHttpActionResult PostFormData() { // Check if the request contains multipart/form-data. if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } var provider = new MultipartMemoryStreamProvider(); try { // Read the form data. var result = Request.Content.ReadAsMultipartAsync(provider).Result; ssortingng response = ""; // This illustrates how to get the file names. foreach (var file in provider.Contents) { var fileName = file.Headers.ContentDisposition.FileName.Trim('\"'); var buffer = file.ReadAsByteArrayAsync().Result; response = HttpUploadFile("https://localhost/api/v1/createfromfile", buffer, fileName, "file", "application/pdf", null, "AuthorizationKey"); } return Ok(response); } catch (System.Exception e) { return InternalServerError(); } } 

J’ai écrit une classe à l’aide de WebClient à l’époque du téléchargement de formulaires en plusieurs parties.

http://ferozedaud.blogspot.com/2010/03/multipart-form-upload-helper.html

 /// /// MimePart /// Abstract class for all MimeParts /// abstract class MimePart { public ssortingng Name { get; set; } public abstract ssortingng ContentDisposition { get; } public abstract ssortingng ContentType { get; } public abstract void CopyTo(Stream stream); public Ssortingng Boundary { get; set; } } class NameValuePart : MimePart { private NameValueCollection nameValues; public NameValuePart(NameValueCollection nameValues) { this.nameValues = nameValues; } public override void CopyTo(Stream stream) { ssortingng boundary = this.Boundary; SsortingngBuilder sb = new SsortingngBuilder(); foreach (object element in this.nameValues.Keys) { sb.AppendFormat("--{0}", boundary); sb.Append("\r\n"); sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\";", element); sb.Append("\r\n"); sb.Append("\r\n"); sb.Append(this.nameValues[element.ToSsortingng()]); sb.Append("\r\n"); } sb.AppendFormat("--{0}", boundary); sb.Append("\r\n"); //Trace.WriteLine(sb.ToSsortingng()); byte [] data = Encoding.ASCII.GetBytes(sb.ToSsortingng()); stream.Write(data, 0, data.Length); } public override ssortingng ContentDisposition { get { return "form-data"; } } public override ssortingng ContentType { get { return Ssortingng.Empty; } } } class FilePart : MimePart { private Stream input; private Ssortingng contentType; public FilePart(Stream input, Ssortingng name, Ssortingng contentType) { this.input = input; this.contentType = contentType; this.Name = name; } public override void CopyTo(Stream stream) { SsortingngBuilder sb = new SsortingngBuilder(); sb.AppendFormat("Content-Disposition: {0}", this.ContentDisposition); if (this.Name != null) sb.Append("; ").AppendFormat("name=\"{0}\"", this.Name); if (this.FileName != null) sb.Append("; ").AppendFormat("filename=\"{0}\"", this.FileName); sb.Append("\r\n"); sb.AppendFormat(this.ContentType); sb.Append("\r\n"); sb.Append("\r\n"); // serialize the header data. byte[] buffer = Encoding.ASCII.GetBytes(sb.ToSsortingng()); stream.Write(buffer, 0, buffer.Length); // send the stream. byte[] readBuffer = new byte[1024]; int read = input.Read(readBuffer, 0, readBuffer.Length); while (read > 0) { stream.Write(readBuffer, 0, read); read = input.Read(readBuffer, 0, readBuffer.Length); } // write the terminating boundary sb.Length = 0; sb.Append("\r\n"); sb.AppendFormat("--{0}", this.Boundary); sb.Append("\r\n"); buffer = Encoding.ASCII.GetBytes(sb.ToSsortingng()); stream.Write(buffer, 0, buffer.Length); } public override ssortingng ContentDisposition { get { return "file"; } } public override ssortingng ContentType { get { return Ssortingng.Format("content-type: {0}", this.contentType); } } public Ssortingng FileName { get; set; } } /// /// Helper class that encapsulates all file uploads /// in a mime part. /// class FilesCollection : MimePart { private List files; public FilesCollection() { this.files = new List(); this.Boundary = MultipartHelper.GetBoundary(); } public int Count { get { return this.files.Count; } } public override ssortingng ContentDisposition { get { return Ssortingng.Format("form-data; name=\"{0}\"", this.Name); } } public override ssortingng ContentType { get { return Ssortingng.Format("multipart/mixed; boundary={0}", this.Boundary); } } public override void CopyTo(Stream stream) { // serialize the headers SsortingngBuilder sb = new SsortingngBuilder(128); sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n"); sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n"); sb.Append("\r\n"); sb.AppendFormat("--{0}", this.Boundary).Append("\r\n"); byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToSsortingng()); stream.Write(headerBytes, 0, headerBytes.Length); foreach (FilePart part in files) { part.Boundary = this.Boundary; part.CopyTo(stream); } } public void Add(FilePart part) { this.files.Add(part); } } /// /// Helper class to aid in uploading multipart /// entities to HTTP web endpoints. /// class MultipartHelper { private static Random random = new Random(Environment.TickCount); private List formData = new List(); private FilesCollection files = null; private MemoryStream bufferStream = new MemoryStream(); private ssortingng boundary; public Ssortingng Boundary { get { return boundary; } } public static Ssortingng GetBoundary() { return Environment.TickCount.ToSsortingng("X"); } public MultipartHelper() { this.boundary = MultipartHelper.GetBoundary(); } public void Add(NameValuePart part) { this.formData.Add(part); part.Boundary = boundary; } public void Add(FilePart part) { if (files == null) { files = new FilesCollection(); } this.files.Add(part); } public void Upload(WebClient client, ssortingng address, ssortingng method) { // set header client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + this.boundary); Trace.WriteLine("Content-Type: multipart/form-data; boundary=" + this.boundary + "\r\n"); // first, serialize the form data foreach (NameValuePart part in this.formData) { part.CopyTo(bufferStream); } // serialize the files. this.files.CopyTo(bufferStream); if (this.files.Count > 0) { // add the terminating boundary. SsortingngBuilder sb = new SsortingngBuilder(); sb.AppendFormat("--{0}", this.Boundary).Append("\r\n"); byte [] buffer = Encoding.ASCII.GetBytes(sb.ToSsortingng()); bufferStream.Write(buffer, 0, buffer.Length); } bufferStream.Seek(0, SeekOrigin.Begin); Trace.WriteLine(Encoding.ASCII.GetSsortingng(bufferStream.ToArray())); byte [] response = client.UploadData(address, method, bufferStream.ToArray()); Trace.WriteLine("----- RESPONSE ------"); Trace.WriteLine(Encoding.ASCII.GetSsortingng(response)); } /// /// Helper class that encapsulates all file uploads /// in a mime part. /// class FilesCollection : MimePart { private List files; public FilesCollection() { this.files = new List(); this.Boundary = MultipartHelper.GetBoundary(); } public int Count { get { return this.files.Count; } } public override ssortingng ContentDisposition { get { return Ssortingng.Format("form-data; name=\"{0}\"", this.Name); } } public override ssortingng ContentType { get { return Ssortingng.Format("multipart/mixed; boundary={0}", this.Boundary); } } public override void CopyTo(Stream stream) { // serialize the headers SsortingngBuilder sb = new SsortingngBuilder(128); sb.Append("Content-Disposition: ").Append(this.ContentDisposition).Append("\r\n"); sb.Append("Content-Type: ").Append(this.ContentType).Append("\r\n"); sb.Append("\r\n"); sb.AppendFormat("--{0}", this.Boundary).Append("\r\n"); byte[] headerBytes = Encoding.ASCII.GetBytes(sb.ToSsortingng()); stream.Write(headerBytes, 0, headerBytes.Length); foreach (FilePart part in files) { part.Boundary = this.Boundary; part.CopyTo(stream); } } public void Add(FilePart part) { this.files.Add(part); } } } class Program { static void Main(ssortingng[] args) { Trace.Listeners.Add(new ConsoleTraceListener()); try { using (StreamWriter sw = new StreamWriter("testfile.txt", false)) { sw.Write("Hello there!"); } using (Stream iniStream = File.OpenRead(@"c:\platform.ini")) using (Stream fileStream = File.OpenRead("testfile.txt")) using (WebClient client = new WebClient()) { MultipartHelper helper = new MultipartHelper(); NameValueCollection props = new NameValueCollection(); props.Add("fname", "john"); props.Add("id", "acme"); helper.Add(new NameValuePart(props)); FilePart filepart = new FilePart(fileStream, "pics1", "text/plain"); filepart.FileName = "1.jpg"; helper.Add(filepart); FilePart ini = new FilePart(iniStream, "pics2", "text/plain"); ini.FileName = "inifile.ini"; helper.Add(ini); helper.Upload(client, "http://localhost/form.aspx", "POST"); } } catch (Exception e) { Trace.WriteLine(e); } } } 

This will work with all versions of the .NET framework.

I can never get the examples to work properly, I always receive a 500 error when sending it to the server.

However I came across a very elegant method of doing it in this url

It is easily extendible and obviously works with binary files as well as XML.

You call it using something similar to this

 class Program { public static ssortingng gsaFeedURL = "http://yourGSA.domain.com:19900/xmlfeed"; static void Main() { try { postWebData(); } catch (Exception ex) { } } // new one I made from C# web service public static void postWebData() { SsortingngDictionary dictionary = new SsortingngDictionary(); UploadSpec uploadSpecs = new UploadSpec(); UTF8Encoding encoding = new UTF8Encoding(); byte[] bytes; Uri gsaURI = new Uri(gsaFeedURL); // Create new URI to GSA feeder gate ssortingng sourceURL = @"C:\FeedFile.xml"; // Location of the XML feed file // Two parameters to send ssortingng feedtype = "full"; ssortingng datasource = "test"; try { // Add the parameter values to the dictionary dictionary.Add("feedtype", feedtype); dictionary.Add("datasource", datasource); // Load the feed file created and get its bytes XmlDocument xml = new XmlDocument(); xml.Load(sourceURL); bytes = Encoding.UTF8.GetBytes(xml.OuterXml); // Add data to upload specs uploadSpecs.Contents = bytes; uploadSpecs.FileName = sourceURL; uploadSpecs.FieldName = "data"; // Post the data if ((int)HttpUpload.Upload(gsaURI, dictionary, uploadSpecs).StatusCode == 200) { Console.WriteLine("Successful."); } else { // GSA POST not successful Console.WriteLine("Failure."); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } 

For me, the following works (mostly inspirated from all of the following answers), I started from Elad’s answer and modify/simplify things to match my need (remove not file form inputs, only one file, …).

Hope it can helps somebody 🙂

(PS: I know that exception handling is not implemented and it assumes that it was written inside a class, so I may need some integration effort…)

 private void uploadFile() { Random rand = new Random(); ssortingng boundary = "----boundary" + rand.Next().ToSsortingng(); Stream data_stream; byte[] header = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"file_path\"; filename=\"" + System.IO.Path.GetFileName(this.file) + "\"\r\nContent-Type: application/octet-stream\r\n\r\n"); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); // Do the request HttpWebRequest request = (HttpWebRequest)WebRequest.Create(MBF_URL); request.UserAgent = "My Toolbox"; request.Method = "POST"; request.KeepAlive = true; request.ContentType = "multipart/form-data; boundary=" + boundary; data_stream = request.GetRequestStream(); data_stream.Write(header, 0, header.Length); byte[] file_bytes = System.IO.File.ReadAllBytes(this.file); data_stream.Write(file_bytes, 0, file_bytes.Length); data_stream.Write(trailer, 0, trailer.Length); data_stream.Close(); // Read the response WebResponse response = request.GetResponse(); data_stream = response.GetResponseStream(); StreamReader reader = new StreamReader(data_stream); this.url = reader.ReadToEnd(); if (this.url == "") { this.url = "No response :("; } reader.Close(); data_stream.Close(); response.Close(); } 

Check out the MyToolkit library:

 var request = new HttpPostRequest("http://www.server.com"); request.Data.Add("name", "value"); // POST data request.Files.Add(new HttpPostFile("name", "file.jpg", "path/to/file.jpg")); await Http.PostAsync(request, OnRequestFinished); 

http://mytoolkit.codeplex.com/wikipage?title=Http

Client use convert File to ToBase64Ssortingng , after use Xml to promulgate to Server call, this server use File.WriteAllBytes(path,Convert.FromBase64Ssortingng(dataFile_Client_sent)) .

Good lucky!

I realize this is probably really late, but I was searching for the same solution. I found the following response from a Microsoft rep

 private void UploadFilesToRemoteUrl(ssortingng url, ssortingng[] files, ssortingng logpath, NameValueCollection nvc) { long length = 0; ssortingng boundary = "----------------------------" + DateTime.Now.Ticks.ToSsortingng("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"); ssortingng formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; foreach(ssortingng key in nvc.Keys) { ssortingng formitem = ssortingng.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); ssortingng 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