Hi Guys,
Today I am going to tell you how to upload a file with parameters to an external API. It is quite useful to send information like profile details of a user to an API. To achieve
this there are two ways which I found to implement the same. The first way is using "RestSharp" which is a library used in C# to call API. This is really simple and allows async
calls which is quite prevalant these days. The second way is to create a utility class and then call the post method to send the details with file stream.
Below are the ways
1. Using RestClient
//First Way Using Nuget Package https://www.nuget.org/packages/RestSharp
//RestRequest for adding parameters
RestRequest request = new RestRequest("http://www.test.com/profiledata.aspx", Method.POST);
request.AddParameter("details", msgTextBox.Text);
request.AddFile("profilepic", Server.MapPath("Myfiles/")+"test.jpg");
//calling server with restClient
RestClient restClient = new RestClient();
restClient.ExecuteAsync(request, (response) =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
//POST successful
}
else
{
//error ocured during POST
}
});
2. Using Utility Class
a. Create a utility class as below
public static class Upload
{
private const string FileFieldNameDefault = "fileContent";
public static WebResponse PostFile
(Uri requestUri, NameValueCollection postData, Stream fileData, string fileName,
string fileContentType, string fileFieldName, CookieContainer cookies,
NameValueCollection headers)
{
ServicePointManager.Expect100Continue = false;
if (requestUri.Scheme == "https")
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, err) => true;
}
var webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
webRequest.Method = "POST";
string boundary = "----------" + DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture);
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
string ctype;
if (string.IsNullOrEmpty(fileContentType))
fileContentType = TryGetContentType(fileName, out ctype)
? ctype
: "application/octet-stream";
fileFieldName = string.IsNullOrEmpty(fileFieldName) ? FileFieldNameDefault : fileFieldName;
if (headers != null)
foreach (string key in headers.AllKeys)
{
var values = headers.GetValues(key);
if (values != null)
foreach (var value in values)
webRequest.Headers.Add(key, value);
}
if (cookies != null)
webRequest.CookieContainer = cookies;
var sbHeader = new StringBuilder();
if (fileData != null)
{
var fileNameValue = string.Empty;
if (string.IsNullOrEmpty(fileName) == false)
fileNameValue = string.Format(CultureInfo.InvariantCulture, "filename=\"{0}\"", Path.GetFileName(fileName));
sbHeader
.AppendFormat("--{0}", boundary)
.AppendLine()
.AppendFormat("Content-Disposition: form-data; name=\"{0}\"; {1}", fileFieldName, fileNameValue)
.AppendLine()
.AppendFormat("Content-Type: {0}", fileContentType)
.AppendLine()
.AppendLine();
}
var sbFooter = new StringBuilder();
sbFooter.AppendLine();
if (postData != null)
foreach (var key in postData.AllKeys)
{
var values = postData.GetValues(key);
if (values != null)
foreach (var value in values)
sbFooter
.AppendFormat("--{0}", boundary)
.AppendLine()
.AppendFormat("Content-Disposition: form-data; name=\"{0}\"", key)
.AppendLine()
.AppendLine()
.Append(value)
.AppendLine();
}
sbFooter.AppendFormat("--{0}--\r\n", boundary);
byte[] header = Encoding.UTF8.GetBytes(sbHeader.ToString());
byte[] footer = Encoding.UTF8.GetBytes(sbFooter.ToString());
long contentLength = header.Length + (fileData != null ? fileData.Length : 0) + footer.Length;
webRequest.ContentLength = contentLength;
using (var requestStream = webRequest.GetRequestStream())
{
requestStream.Write(header, 0, header.Length);
if (fileData != null)
{
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fileData.Read(buffer, 0, buffer.Length)) != 0)
requestStream.Write(buffer, 0, bytesRead);
}
requestStream.Write(footer, 0, footer.Length);
return webRequest.GetResponse();
}
}
public static WebResponse PostFile
(Uri requestUri, NameValueCollection postData, string fileName,
string fileContentType, string fileFieldName, CookieContainer cookies,
NameValueCollection headers)
{
using (var fileData = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
return PostFile(requestUri, postData, fileData,
fileName, fileContentType, fileFieldName, cookies,
headers);
}
private static bool TryGetContentType(string fileName, out string contentType)
{
try
{
RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type");
if (key != null)
{
foreach (string keyName in from keyName in key.GetSubKeyNames()
let subKey = key.OpenSubKey(keyName)
where subKey != null
let subKeyValue = (string)subKey.GetValue("Extension")
where string.IsNullOrEmpty(subKeyValue) == false
where string.Compare(Path.GetExtension(fileName), subKeyValue, StringComparison.OrdinalIgnoreCase) == 0
select keyName)
{
contentType = keyName;
return true;
}
}
}
catch
{
// fail silently
// TODO: rethrow registry access denied errors
}
contentType = string.Empty;
return false;
}
}
b. call the api using this example
//Thanks to http://stackoverflow.com/questions/7382786/uploading-a-file-using-application-x-www-form-urlencoded
//Get the file name and save it in a stream
string filename = Server.MapPath("~/ProfileFile/sampleCSV.csv");
FileStream fileData = new FileStream(filename, FileMode.Open, FileAccess.Read);
//Add the form values in the collection
NameValueCollection frmValues = new NameValueCollection();
frmValues.Add("method", "myUpload");
frmValues.Add("userid", "xxxxxxxxx");
frmValues.Add("password", "xxxxxxxx");
frmValues.Add("xlsFile", filename);
//Get the path of the target url
Uri u=new Uri("http://www.test.com/GatewayAPI/rest");
//Get the name value collection of headers
//NameValueCollection headers = base.Request.Headers;
NameValueCollection headers = null;
//Post the data
Upload.PostFile(u, frmValues, fileData, filename, "text/csv", "xlsFile", null, headers);
Thanks and Enjoy!!
Today I am going to tell you how to upload a file with parameters to an external API. It is quite useful to send information like profile details of a user to an API. To achieve
this there are two ways which I found to implement the same. The first way is using "RestSharp" which is a library used in C# to call API. This is really simple and allows async
calls which is quite prevalant these days. The second way is to create a utility class and then call the post method to send the details with file stream.
Below are the ways
1. Using RestClient
//First Way Using Nuget Package https://www.nuget.org/packages/RestSharp
//RestRequest for adding parameters
RestRequest request = new RestRequest("http://www.test.com/profiledata.aspx", Method.POST);
request.AddParameter("details", msgTextBox.Text);
request.AddFile("profilepic", Server.MapPath("Myfiles/")+"test.jpg");
//calling server with restClient
RestClient restClient = new RestClient();
restClient.ExecuteAsync(request, (response) =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
//POST successful
}
else
{
//error ocured during POST
}
});
2. Using Utility Class
a. Create a utility class as below
public static class Upload
{
private const string FileFieldNameDefault = "fileContent";
public static WebResponse PostFile
(Uri requestUri, NameValueCollection postData, Stream fileData, string fileName,
string fileContentType, string fileFieldName, CookieContainer cookies,
NameValueCollection headers)
{
ServicePointManager.Expect100Continue = false;
if (requestUri.Scheme == "https")
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, err) => true;
}
var webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
webRequest.Method = "POST";
string boundary = "----------" + DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture);
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
string ctype;
if (string.IsNullOrEmpty(fileContentType))
fileContentType = TryGetContentType(fileName, out ctype)
? ctype
: "application/octet-stream";
fileFieldName = string.IsNullOrEmpty(fileFieldName) ? FileFieldNameDefault : fileFieldName;
if (headers != null)
foreach (string key in headers.AllKeys)
{
var values = headers.GetValues(key);
if (values != null)
foreach (var value in values)
webRequest.Headers.Add(key, value);
}
if (cookies != null)
webRequest.CookieContainer = cookies;
var sbHeader = new StringBuilder();
if (fileData != null)
{
var fileNameValue = string.Empty;
if (string.IsNullOrEmpty(fileName) == false)
fileNameValue = string.Format(CultureInfo.InvariantCulture, "filename=\"{0}\"", Path.GetFileName(fileName));
sbHeader
.AppendFormat("--{0}", boundary)
.AppendLine()
.AppendFormat("Content-Disposition: form-data; name=\"{0}\"; {1}", fileFieldName, fileNameValue)
.AppendLine()
.AppendFormat("Content-Type: {0}", fileContentType)
.AppendLine()
.AppendLine();
}
var sbFooter = new StringBuilder();
sbFooter.AppendLine();
if (postData != null)
foreach (var key in postData.AllKeys)
{
var values = postData.GetValues(key);
if (values != null)
foreach (var value in values)
sbFooter
.AppendFormat("--{0}", boundary)
.AppendLine()
.AppendFormat("Content-Disposition: form-data; name=\"{0}\"", key)
.AppendLine()
.AppendLine()
.Append(value)
.AppendLine();
}
sbFooter.AppendFormat("--{0}--\r\n", boundary);
byte[] header = Encoding.UTF8.GetBytes(sbHeader.ToString());
byte[] footer = Encoding.UTF8.GetBytes(sbFooter.ToString());
long contentLength = header.Length + (fileData != null ? fileData.Length : 0) + footer.Length;
webRequest.ContentLength = contentLength;
using (var requestStream = webRequest.GetRequestStream())
{
requestStream.Write(header, 0, header.Length);
if (fileData != null)
{
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fileData.Read(buffer, 0, buffer.Length)) != 0)
requestStream.Write(buffer, 0, bytesRead);
}
requestStream.Write(footer, 0, footer.Length);
return webRequest.GetResponse();
}
}
public static WebResponse PostFile
(Uri requestUri, NameValueCollection postData, string fileName,
string fileContentType, string fileFieldName, CookieContainer cookies,
NameValueCollection headers)
{
using (var fileData = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
return PostFile(requestUri, postData, fileData,
fileName, fileContentType, fileFieldName, cookies,
headers);
}
private static bool TryGetContentType(string fileName, out string contentType)
{
try
{
RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type");
if (key != null)
{
foreach (string keyName in from keyName in key.GetSubKeyNames()
let subKey = key.OpenSubKey(keyName)
where subKey != null
let subKeyValue = (string)subKey.GetValue("Extension")
where string.IsNullOrEmpty(subKeyValue) == false
where string.Compare(Path.GetExtension(fileName), subKeyValue, StringComparison.OrdinalIgnoreCase) == 0
select keyName)
{
contentType = keyName;
return true;
}
}
}
catch
{
// fail silently
// TODO: rethrow registry access denied errors
}
contentType = string.Empty;
return false;
}
}
b. call the api using this example
//Thanks to http://stackoverflow.com/questions/7382786/uploading-a-file-using-application-x-www-form-urlencoded
//Get the file name and save it in a stream
string filename = Server.MapPath("~/ProfileFile/sampleCSV.csv");
FileStream fileData = new FileStream(filename, FileMode.Open, FileAccess.Read);
//Add the form values in the collection
NameValueCollection frmValues = new NameValueCollection();
frmValues.Add("method", "myUpload");
frmValues.Add("userid", "xxxxxxxxx");
frmValues.Add("password", "xxxxxxxx");
frmValues.Add("xlsFile", filename);
//Get the path of the target url
Uri u=new Uri("http://www.test.com/GatewayAPI/rest");
//Get the name value collection of headers
//NameValueCollection headers = base.Request.Headers;
NameValueCollection headers = null;
//Post the data
Upload.PostFile(u, frmValues, fileData, filename, "text/csv", "xlsFile", null, headers);
Thanks and Enjoy!!