Created
February 10, 2012 13:58
-
-
Save bgrins/1789787 to your computer and use it in GitHub Desktop.
C# Multipart File Upload
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Implements multipart/form-data POST in C# http://www.ietf.org/rfc/rfc2388.txt | |
// http://www.briangrinstead.com/blog/multipart-form-post-in-c | |
public static class FormUpload | |
{ | |
private static readonly Encoding encoding = Encoding.UTF8; | |
public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters) | |
{ | |
string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid()); | |
string contentType = "multipart/form-data; boundary=" + formDataBoundary; | |
byte[] formData = GetMultipartFormData(postParameters, formDataBoundary); | |
return PostForm(postUrl, userAgent, contentType, formData); | |
} | |
private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData) | |
{ | |
HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest; | |
if (request == null) | |
{ | |
throw new NullReferenceException("request is not a http request"); | |
} | |
// Set up the request properties. | |
request.Method = "POST"; | |
request.ContentType = contentType; | |
request.UserAgent = userAgent; | |
request.CookieContainer = new CookieContainer(); | |
request.ContentLength = formData.Length; | |
// You could add authentication here as well if needed: | |
// request.PreAuthenticate = true; | |
// request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested; | |
// request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("username" + ":" + "password"))); | |
// Send the form data to the request. | |
using (Stream requestStream = request.GetRequestStream()) | |
{ | |
requestStream.Write(formData, 0, formData.Length); | |
requestStream.Close(); | |
} | |
return request.GetResponse() as HttpWebResponse; | |
} | |
private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary) | |
{ | |
Stream formDataStream = new System.IO.MemoryStream(); | |
bool needsCLRF = false; | |
foreach (var param in postParameters) | |
{ | |
// Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added. | |
// Skip it on the first parameter, add it to subsequent parameters. | |
if (needsCLRF) | |
formDataStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n")); | |
needsCLRF = true; | |
if (param.Value is FileParameter) | |
{ | |
FileParameter fileToUpload = (FileParameter)param.Value; | |
// Add just the first part of this param, since we will write the file data directly to the Stream | |
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", | |
boundary, | |
param.Key, | |
fileToUpload.FileName ?? param.Key, | |
fileToUpload.ContentType ?? "application/octet-stream"); | |
formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header)); | |
// Write the file data directly to the Stream, rather than serializing it to a string. | |
formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length); | |
} | |
else | |
{ | |
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", | |
boundary, | |
param.Key, | |
param.Value); | |
formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData)); | |
} | |
} | |
// Add the end of the request. Start with a newline | |
string footer = "\r\n--" + boundary + "--\r\n"; | |
formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer)); | |
// Dump the Stream into a byte[] | |
formDataStream.Position = 0; | |
byte[] formData = new byte[formDataStream.Length]; | |
formDataStream.Read(formData, 0, formData.Length); | |
formDataStream.Close(); | |
return formData; | |
} | |
public class FileParameter | |
{ | |
public byte[] File { get; set; } | |
public string FileName { get; set; } | |
public string ContentType { get; set; } | |
public FileParameter(byte[] file) : this(file, null) { } | |
public FileParameter(byte[] file, string filename) : this(file, filename, null) { } | |
public FileParameter(byte[] file, string filename, string contenttype) | |
{ | |
File = file; | |
FileName = filename; | |
ContentType = contenttype; | |
} | |
} | |
} |
Cool, its work, but for correctness receiving:
d.Add(name, f);
Where name - name of POST variable, by this name could receive data on server.
can you give simple example what are the parameter need to pass i have
file with absulte parh and URL which i need to post file there
Good class.
FileParameter needs a filename only constructor that opens the file then streams it out to the server, since I do not want to load a video file into memory then stream out.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Many thanks for sharing this with us.
Im trying the following and Im not so sure Im doing it right as I'm getting a weird response.
Here is my object ini:
string CT = "image/jpeg";
string fullPath = "C:\inetpub\wwwroot\dev.xxxx.com\1.jpg";
FormUpload.FileParameter f = new FormUpload.FileParameter(File.ReadAllBytes(fullPath), "1.jpg", "multipart/form-data");
Dictionary<string,object> d = new Dictionary<string,object>();
d.Add(CT, f);
string ua = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
FormUpload.MultipartFormDataPost(url, ua, d);
Will appreciate any input.
regards,
mkariti