How Decompress Gzipped Http Get Response in c# - c#

Want to Decompress a Response which is GZipped Getting from an API.Tried the Below Code ,It Always return Like:-
\u001f�\b\0\0\0\0\0\0\0�Y]o........
My code is:
private string GetResponse(string sData, string sUrl)
{
try
{
string script = null;
try
{
string urlStr = #"" + sUrl + "?param=" + sData;
Uri url = new Uri(urlStr, UriKind.Absolute);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
script = reader.ReadToEnd();
}
}
catch (System.Net.Sockets.SocketException)
{
// The remote site is currently down. Try again next time.
}
catch (UriFormatException)
{
// Only valid absolute URLs are accepted
}
return script;
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
I Found the Above Code from many References for Automatic Decompression.But Eventually,it doesn't Work for me.So as to Unzip the zipped Data I tried the Below Function,
private string DecompressGZIP(string compressedText)
{
byte[] gZipBuffer = Convert.FromBase64String(compressedText);
using (var memoryStream = new MemoryStream())
{
int dataLength = BitConverter.ToInt32(gZipBuffer, 0);
memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4);
var buffer = new byte[dataLength];
memoryStream.Position = 0;
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
{
gZipStream.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
}
But,it also Failed in the First Line of code itself Because of the Following Exception:
System.FormatException: 'The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. '
As i am a Beginner,Hope You guys will Guide Me .....Thanks in advance....

This is the essential bit which will take care of decoding the gzipped stream:
var clientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
var client = new HttpClient(clientHandler);

Just Change My Function as Follows,Which is Perfectly Working For me:
private JObject PostingToPKFAndDecompress(string sData, string sUrl)
{
var jOBj = new JObject();
try
{
try
{
string urlStr = #"" + sUrl + "?param=" + sData;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlStr);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream resStream = response.GetResponseStream();
var t = ReadFully(resStream);
var y = Decompress(t);
using (var ms = new MemoryStream(y))
using (var streamReader = new StreamReader(ms))
using (var jsonReader = new JsonTextReader(streamReader))
{
jOBj = (JObject)JToken.ReadFrom(jsonReader);
}
}
catch (System.Net.Sockets.SocketException)
{
// The remote site is currently down. Try again next time.
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
return jOBj;
}
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
public static byte[] Decompress(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}

Related

Http post method hanging before getting response using c# [duplicate]

Failed to get response for large file HTTP put create file using c#
I am using file watcher service service monitor, when user created file or folder we are uploading to cloud
if file size more than 512 MB it is taking too much time to get the response
here I am confusing here the issue with my code or server
and reason for this error
if any changes on my code suggest me.
{
var fileFolderObj1 = new FileFolder();
var postURL = apiBaseUri + "/filefolder/create/file/user/" + userId; // +"?type=file";
code = HttpStatusCode.OK;
HttpWebResponse response = null;
FileInfo f = new FileInfo(filePath);
long filesizeF = f.Length;
try
{
string selectedFile = null;
selectedFile = filePath;
var fi = System.IO.Path.GetFileName(filePath);
////commented for some reason
var postParameters = new Dictionary<string, object>();
postParameters.Add("file", new FileParameter(filePath, ""));
postParameters.Add("parentId", parentId);
postParameters.Add("newName", fi);
postParameters.Add("cloudId", cloudId);
postParameters.Add("isSecure", isSecure);
//postParameters.Add("fileSize", fi.Length);
postParameters.Add("fileSize", filesizeF);
var userAgent = "Desktop";
var formDataBoundary = "----WebKitFormBoundary" + DateTime.Now.Ticks.ToString("x");
var uri = new Uri(postURL);
var createFileRequest = WebRequest.Create(uri) as HttpWebRequest;
this.SetBasicAuthHeader(createFileRequest, userId, password);
createFileRequest.ContentType = "multipart/form-data";
createFileRequest.Method = "PUT";
createFileRequest.Timeout = System.Threading.Timeout.Infinite;
createFileRequest.KeepAlive = false;/*true;*/
createFileRequest.UserAgent = userAgent;
createFileRequest.CookieContainer = new CookieContainer();
try
{
using (var requestStream = createFileRequest.GetRequestStream())
{
}
using (response = (HttpWebResponse)createFileRequest.GetResponse())
{
StreamReader(response.GetResponseStream()).ReadToEnd();
fileFolderObj1 = JsonConvert.DeserializeObject<FileFolder>(reslut);
}
}
catch (Exception exc)
{
if (response != null)
{
code = response.StatusCode;
}
}
}
catch (Exception exc)
{
}
}
}
private static readonly Encoding encoding = Encoding.UTF8;
private void WriteMultipartFormData(Dictionary<string, object> postParameters, string boundary, Stream requestStream, ILogService logService = null)
{
var needsCLRF = false;
foreach (var param in postParameters)
{
// Skip it on the first parameter, add it to subsequent parameters.
if (needsCLRF)
{
requestStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
}
needsCLRF = true;
if (param.Value is FileParameter)
{
var fileToUpload = (FileParameter)param.Value;
// Add just the first part of this param, since we will write the file data directly to the Stream
var 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");
requestStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
FileStream fileStream = new FileStream(fileToUpload.FileName, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0,buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
logService.Debug("WRITEMULTIPART FORM DATA Bufferlent Running :{0}", bytesRead);
}
fileStream.Close();
}
else
{
var postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
param.Value);
requestStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
}
}
// Add the end of the request. Start with a newline
var footer = "\r\n--" + boundary + "--\r\n";
requestStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
}
}

Telegram Bot custom keyboard in C#

I tried to create message with custom keyboard. So I send request with
reply_markup = {"keyboard":[["1"],["2"]],"resize_keyboard":"True","one_time_keyboard":"True"}
But, it does not work.
I tried all of Content-Types:
application/x-www-form-urlencoded (create message with default
keyboard)
application/json (create message with default keyboard)
multipart/form-data (does not work at all, inspite of this Post)
I also tried to send message by 2 different ways. What's the wrong with this code?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
namespace DutyReminder
{
class Program
{
static void Main(string[] args)
{
string message = "message";
string message1 = "message1";
string botid = "165749848:AAGtjn42bajF-WxdKosTF07sLwJPYlqiDZE";
string chatid = "38651047";
Sender.send("", "https://api.telegram.org/bot" + botid + "/sendmessage?chat_id=" + chatid + "&text=" + message + "&reply_markup={\"keyboard\":[[\"1\"],[\"2\"]],\"resize_keyboard\":\"True\",\"one_time_keyboard\":\"True\"}");
Sender.HttpPost("https://api.telegram.org/bot" + botid + "/sendmessage?chat_id=" + chatid + "&text=" + message1 + "&reply_markup={\"keyboard\":[[\"1\"],[\"2\"]],\"resize_keyboard\":\"True\",\"one_time_keyboard\":\"True\"}", "");
}
}
static class Sender
{
static public void send(string message, string url)
{
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create(url);
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
//string postData = "{\"value1\":\"" + message + "\"}";
string postData = message;
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
// request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
}
static public string HttpPost(string URI, string Parameters)
{
System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
// req.Proxy = new System.Net.WebProxy(ProxyString, true);
//Add these, as we're doing a POST
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
//We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value&
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
req.ContentLength = bytes.Length;
System.IO.Stream os = req.GetRequestStream();
os.Write(bytes, 0, bytes.Length); //Push it out there
os.Close();
System.Net.WebResponse resp = req.GetResponse();
if (resp == null) return null;
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}
}
}
Use the following instead of URI message sending:
var bot = new Api("YourApiToken");
.
.
.
var rmu = new ReplyKeyboardMarkup();
rmu.Keyboard =
new string[][]
{
new string[] {"1-1", "1-2"},
new string[] {"2"},
new string[] {"3-1", "3-2" , "3-3" }
};
await bot.SendTextMessage(update.Message.Chat.Id, msg, false, 0, rmu);
UPDATED
With the newer version of API:
var bot = new Api("YourApiToken");
.
.
.
var rkm = new ReplyKeyboardMarkup();
rkm.Keyboard =
new KeyboardButton[][]
{
new KeyboardButton[]
{
new KeyboardButton("1-1"),
new KeyboardButton("1-2")
},
new KeyboardButton[]
{
new KeyboardButton("2")
},
new KeyboardButton[]
{
new KeyboardButton("3-1"),
new KeyboardButton("3-2"),
new KeyboardButton("3-3")
}
};
await bot.SendTextMessage(update.Message.Chat.Id, msg, false, false, 0, rkm );
You can dynamicly create keyboard.
var rkm = new ReplyKeyboardMarkup();
var rows = new List<KeyboardButton[]>();
var cols = new List<KeyboardButton>();
for (var Index = 1; Index < 17; Index++)
{
cols.Add(new KeyboardButton("" + Index));
if (Index%4 != 0) continue;
rows.Add(cols.ToArray());
cols = new List<KeyboardButton>();
}
rkm.Keyboard = rows.ToArray();
await botClient.SendTextMessageAsync(
message.Chat.Id,
"Choose",
replyMarkup: rkm);
I did it my way :)
public static class KeyboardHelper
{
public static ReplyKeyboardMarkup GetKeyboard(List<string> keys)
{
var rkm = new ReplyKeyboardMarkup();
var rows = new List<KeyboardButton[]>();
var cols = new List<KeyboardButton>();
foreach (var t in keys)
{
cols.Add(new KeyboardButton(t));
rows.Add(cols.ToArray());
cols = new List<KeyboardButton>();
}
rkm.Keyboard = rows.ToArray();
return rkm;
}
}
List<string> items = new List<string>();
items.Add("A");
items.Add("B");
items.Add("C");
items.Add("D");
items.Add("E");
var rkm = new ReplyKeyboardMarkup();
var rows = new List<KeyboardButton[]>();
var cols = new List<KeyboardButton>();
for (var Index = 1; Index < items.Count+1; Index++)
{
cols.Add(new KeyboardButton("" + items[Index-1]));
if (Index % 4 != 0) continue;
rows.Add(cols.ToArray());
cols = new List<KeyboardButton>();
}
if (cols.Count > 0) {rows.Add(cols.ToArray());}
rkm.Keyboard = rows.ToArray();
await Bot.SendTextMessageAsync(message.Chat.Id,"Choose",replyMarkup: rkm);

HttpWebRequest BeginGetResponse not working

I'm trying use HttpWebRequest, and my BeginGetRequestStream works but it never enters the BeginGetResponse function and i have no idea why.. i've searched for a couple of hours and have not found a solution that works
public void Initialize(IScheduler scheduler)
{
if(_isCloud)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_cloudMappingServer + "/Mapping/GetAllCentralPoints");
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(ReleaseReadCallback), request);
// Instruct the thread to wait until we resume it
_waitHandle.WaitOne();
_waitHandle.Dispose();
}
}
private void ReleaseReadCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest httpRequest = (HttpWebRequest)asynchronousResult.AsyncState;
using (Stream postStream = httpRequest.EndGetRequestStream(asynchronousResult))
{
using (MemoryStream memStream = new MemoryStream())
{
string queryString = string.Empty;
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(queryString);
memStream.Write(bytes, 0, bytes.Length);
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
postStream.Write(tempBuffer, 0, tempBuffer.Length);
}
}
httpRequest.BeginGetResponse(new AsyncCallback(ReleaseResponseCallback), httpRequest);
}
catch (Exception ex)
{
var test = ex;
}
}
private void ReleaseResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest responseRequest = (HttpWebRequest)asynchronousResult.AsyncState;
string responseString = string.Empty;
try
{
using (HttpWebResponse resp = (HttpWebResponse)responseRequest.EndGetResponse(asynchronousResult))
{
using (StreamReader streamRead = new StreamReader(resp.GetResponseStream()))
{
responseString = streamRead.ReadToEnd();
try
{
JsonSerializerSettings settings = new JsonSerializerSettings();
List<CentralPointViewModel> _allCentralPointViewModel = JsonConvert.DeserializeObject<List<CentralPointViewModel>>(responseString, settings);
}
catch (JsonReaderException)
{
responseString = responseString.Replace('\"'.ToString(), string.Empty);
string[] responseArray = responseString.Split(';');
}
catch (JsonSerializationException)
{
responseString = responseString.Replace('\"'.ToString(), string.Empty);
}
}
}
}
catch (Exception ex)
{
}
}
It never enters the ReleaseResponseCallback function! I am able to make my server call but the response never reaches me or I am not properly receiving it.. Any help is appreciated

HttpWebRequest GET returns 'No Content' after successful POST

I'm working on an app that makes a POST to a REST API that returns a URI in its response. I then am to make a GET request to that URI and it is supposed to return HTML content in the response body. However, the GET request returns 'No Content' in its HTTP Status Code.
What's strange is, I have a small console app I built for testing purposes that if I plug the URI into it (allows me to test the GET without making the POST), the status good is 200 - OK and I receive the HTML content in the body. So it seems it is related to something I'm doing in my POST request. Here is my code (sensitive info has been redacted):
private PersonReportResults POSTReportRequest(PersonReportRequest reportRequest)
{
var personReportResults = new PersonReportResults();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://xxxxxxxxx.com/api/v1/personReport/reportResults");
var xDoc = new XmlDocument();
var serializedXml = Serialize(reportRequest);
xDoc.LoadXml(serializedXml);
var bytes = Encoding.ASCII.GetBytes(xDoc.OuterXml);
request.ContentType = "application/xml; encoding='utf-8'";
request.ContentLength = bytes.Length;
request.Method = "POST";
request.KeepAlive = true;
request.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["XXXXXUserId"], ConfigurationManager.AppSettings["XXXXXPassword"]);
request.ClientCertificates.Add(GetClientCertificate());
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
var responseStream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
var count = 0;
do
{
byte[] buf = new byte[1024];
count = responseStream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while (responseStream.CanRead && count > 0);
ms.Position = 0;
// now attempt to desrialize from the memory stream
var serializer = new XmlSerializer(typeof(PersonReportResults));
personReportResults = ((PersonReportResults)serializer.Deserialize(ms));
}
response.Close();
}
request.Abort();
}
return personReportResults;
}
/// <summary>
/// Makes a HTTP GET request for the report HTML
/// </summary>
/// <param name="uri">The URI.</param>
/// <returns>string</returns>
private static string GETResults(string uri)
{
var responseHTML = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri + "?reportType=html");
//request.ContentType = "application/xml; encoding='utf-8'";
request.Method = "GET";
request.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["XXXXXUserId"], ConfigurationManager.AppSettings["XXXXXPassword"]);
request.ClientCertificates.Add(GetClientCertificate());
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
try
{
using (var stream = response.GetResponseStream())
{
if (stream != null)
{
using (MemoryStream ms = new MemoryStream())
{
var count = 0;
do
{
byte[] buf = new byte[1024];
count = stream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while (stream.CanRead && count > 0);
ms.Position = 0;
var sr = new StreamReader(ms);
responseHTML = sr.ReadToEnd();
}
//var reader = new StreamReader(stream, Encoding.UTF8);
//responseHTML = reader.ReadToEnd();
}
}
}
catch (Exception e)
{
}
request.Abort();
}
else if (response.StatusCode == HttpStatusCode.Accepted)
{
response.Close();
var tryCount = 1;
while (tryCount < 5)
{
using (var retryResponse = (HttpWebResponse)request.GetResponse())
{
if (retryResponse.StatusCode == HttpStatusCode.OK)
{
using (var stream = retryResponse.GetResponseStream())
{
if (stream != null)
{
var reader = new StreamReader(stream, Encoding.UTF8);
responseHTML = reader.ReadToEnd();
}
}
}
}
tryCount++;
Thread.Sleep(10000);
}
}
}
return responseHTML;
}

How to upload file to server with HTTP POST multipart/form-data?

I am developing Windows Phone 8 app. I want to upload SQLite database via PHP web service using HTTP POST request with MIME type multipart/form-data & a string data called "userid=SOME_ID".
I don't want to use 3rd party libs like HttpClient, RestSharp or MyToolkit. I tried the below code but it doesn't upload the file & also doesn't give me any errors. It's working fine in Android, PHP, etc so there's no issue in web service. Below is my given code (for WP8). what's wrong with it?
I've googled and I'm not getting specific for WP8
async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(DBNAME);
//Below line gives me file with 0 bytes, why? Should I use
//IsolatedStorageFile instead of StorageFile
//var file = await ApplicationData.Current.LocalFolder.GetFileAsync(DBNAME);
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}
//var res = await HttpPost(Util.UPLOAD_BACKUP, fileBytes);
HttpPost(fileBytes);
}
private void HttpPost(byte[] file_bytes)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.myserver.com/upload.php");
httpWebRequest.ContentType = "multipart/form-data";
httpWebRequest.Method = "POST";
var asyncResult = httpWebRequest.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, file_bytes); }, httpWebRequest);
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)
{
//DON'T KNOW HOW TO PASS "userid=some_user_id"
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asynchronousResult);
postStream.Write(postData, 0, postData.Length);
postStream.Close();
var asyncResult = request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamResponse.Close();
streamRead.Close();
response.Close();
}
I also tried to solve my problem in Windows 8 but it's also not working.
public async Task Upload(byte[] fileBytes)
{
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(new MemoryStream(fileBytes)));
//Not sure below line is true or not
content.Add(new StringContent("userid=farhanW8"));
using (var message = await client.PostAsync("http://www.myserver.com/upload.php", content))
{
var input = await message.Content.ReadAsStringAsync();
}
}
}
}
Basic implementation using MultipartFormDataContent :-
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");
form.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
Here's my final working code. My web service needed one file (POST parameter name was "file") & a string value (POST parameter name was "userid").
/// <summary>
/// Occurs when upload backup application bar button is clicked. Author : Farhan Ghumra
/// </summary>
private async void btnUploadBackup_Click(object sender, EventArgs e)
{
var dbFile = await ApplicationData.Current.LocalFolder.GetFileAsync(Util.DBNAME);
var fileBytes = await GetBytesAsync(dbFile);
var Params = new Dictionary<string, string> { { "userid", "9" } };
UploadFilesToServer(new Uri(Util.UPLOAD_BACKUP), Params, Path.GetFileName(dbFile.Path), "application/octet-stream", fileBytes);
}
/// <summary>
/// Creates HTTP POST request & uploads database to server. Author : Farhan Ghumra
/// </summary>
private void UploadFilesToServer(Uri uri, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.Method = "POST";
httpWebRequest.BeginGetRequestStream((result) =>
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream requestStream = request.EndGetRequestStream(result))
{
WriteMultipartForm(requestStream, boundary, data, fileName, fileContentType, fileData);
}
request.BeginGetResponse(a =>
{
try
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new StreamReader(responseStream))
{
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
string responseString = streamReader.ReadToEnd();
//responseString is depend upon your web service.
if (responseString == "Success")
{
MessageBox.Show("Backup stored successfully on server.");
}
else
{
MessageBox.Show("Error occurred while uploading backup on server.");
}
}
}
}
catch (Exception)
{
}
}, null);
}
catch (Exception)
{
}
}, httpWebRequest);
}
/// <summary>
/// Writes multi part HTTP POST request. Author : Farhan Ghumra
/// </summary>
private void WriteMultipartForm(Stream s, string boundary, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
/// The first boundary
byte[] boundarybytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
/// the last boundary.
byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
/// the form data, properly formatted
string formdataTemplate = "Content-Dis-data; name=\"{0}\"\r\n\r\n{1}";
/// the form-data file upload, properly formatted
string fileheaderTemplate = "Content-Dis-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";
/// Added to track if we need a CRLF or not.
bool bNeedsCRLF = false;
if (data != null)
{
foreach (string key in data.Keys)
{
/// if we need to drop a CRLF, do that.
if (bNeedsCRLF)
WriteToStream(s, "\r\n");
/// Write the boundary.
WriteToStream(s, boundarybytes);
/// Write the key.
WriteToStream(s, string.Format(formdataTemplate, key, data[key]));
bNeedsCRLF = true;
}
}
/// If we don't have keys, we don't need a crlf.
if (bNeedsCRLF)
WriteToStream(s, "\r\n");
WriteToStream(s, boundarybytes);
WriteToStream(s, string.Format(fileheaderTemplate, "file", fileName, fileContentType));
/// Write the file data to the stream.
WriteToStream(s, fileData);
WriteToStream(s, trailer);
}
/// <summary>
/// Writes string to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, string txt)
{
byte[] bytes = Encoding.UTF8.GetBytes(txt);
s.Write(bytes, 0, bytes.Length);
}
/// <summary>
/// Writes byte array to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, byte[] bytes)
{
s.Write(bytes, 0, bytes.Length);
}
/// <summary>
/// Returns byte array from StorageFile. Author : Farhan Ghumra
/// </summary>
private async Task<byte[]> GetBytesAsync(StorageFile file)
{
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}
return fileBytes;
}
I am very much thankful to Darin Rousseau for helping me.
This simplistic version also works.
public void UploadMultipart(byte[] file, string filename, string contentType, string url)
{
var webClient = new WebClient();
string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
var fileData = webClient.Encoding.GetString(file);
var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, filename, contentType, fileData);
var nfile = webClient.Encoding.GetBytes(package);
byte[] resp = webClient.UploadData(url, "POST", nfile);
}
Add any extra required headers if needed.
I've been playing around a little bit and came up with a simplified, more generic solution:
private static string sendHttpRequest(string url, NameValueCollection values, NameValueCollection files = null)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
// The first boundary
byte[] boundaryBytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
// The last boundary
byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
// The first time it itereates, we need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick
byte[] boundaryBytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
// Create the request and set parameters
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;
// Get request stream
Stream requestStream = request.GetRequestStream();
foreach (string key in values.Keys)
{
// Write item to stream
byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}", key, values[key]));
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
requestStream.Write(formItemBytes, 0, formItemBytes.Length);
}
if (files != null)
{
foreach(string key in files.Keys)
{
if(File.Exists(files[key]))
{
int bytesRead = 0;
byte[] buffer = new byte[2048];
byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", key, files[key]));
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
requestStream.Write(formItemBytes, 0, formItemBytes.Length);
using (FileStream fileStream = new FileStream(files[key], FileMode.Open, FileAccess.Read))
{
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
// Write file content to stream, byte by byte
requestStream.Write(buffer, 0, bytesRead);
}
fileStream.Close();
}
}
}
}
// Write trailer and close stream
requestStream.Write(trailer, 0, trailer.Length);
requestStream.Close();
using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()))
{
return reader.ReadToEnd();
};
}
You can use it like this:
string fileLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "somefile.jpg";
NameValueCollection values = new NameValueCollection();
NameValueCollection files = new NameValueCollection();
values.Add("firstName", "Alan");
files.Add("profilePicture", fileLocation);
sendHttpRequest("http://example.com/handler.php", values, files);
And in the PHP script you could handle data like this:
echo $_POST['firstName'];
$name = $_POST['firstName'];
$image = $_FILES['profilePicture'];
$ds = DIRECTORY_SEPARATOR;
move_uploaded_file($image['tmp_name'], realpath(dirname(__FILE__)) . $ds . "uploads" . $ds . $image['name']);
You can use this class:
using System.Collections.Specialized;
class Post_File
{
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
byte[] boundarybytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n"); // the first time it itereates, you need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick.
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
wr.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
var nvc2 = new NameValueCollection();
nvc2.Add("Accepts-Language", "en-us,en;q=0.5");
wr.Headers.Add(nvc2);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
Stream rs = wr.GetRequestStream();
bool firstLoop = true;
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
if (firstLoop)
{
rs.Write(boundarybytesF, 0, boundarybytesF.Length);
firstLoop = false;
}
else
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
}
string formitem = string.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);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, new FileInfo(file).Name, 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);
}
catch (Exception ex)
{
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
}
use it:
NameValueCollection nvc = new NameValueCollection();
//nvc.Add("id", "TTR");
nvc.Add("table_name", "uploadfile");
nvc.Add("commit", "uploadfile");
Post_File.HttpUploadFile("http://example/upload_file.php", #"C:\user\yourfile.docx", "uploadfile", "application/vnd.ms-excel", nvc);
example server upload_file.php:
m('File upload '.(#copy($_FILES['uploadfile']['tmp_name'],getcwd().'\\'.'/'.$_FILES['uploadfile']['name']) ? 'success' : 'failed'));
function m($msg) {
echo '<div style="background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;">';
echo $msg;
echo '</div>';
}
Here is what worked for me while sending the file as mult-form data:
public T HttpPostMultiPartFileStream<T>(string requestURL, string filePath, string fileName)
{
string content = null;
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
StreamContent streamContent;
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
streamContent = new StreamContent(fileStream);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
streamContent.Headers.Add("Content-Disposition", string.Format("form-data; name=\"file\"; filename=\"{0}\"", fileName));
form.Add(streamContent, "file", fileName);
using (HttpClient client = GetAuthenticatedHttpClient())
{
HttpResponseMessage response = client.PostAsync(requestURL, form).GetAwaiter().GetResult();
content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
try
{
return JsonConvert.DeserializeObject<T>(content);
}
catch (Exception ex)
{
// Log the exception
}
return default(T);
}
}
}
}
GetAuthenticatedHttpClient used above can be:
private HttpClient GetAuthenticatedHttpClient()
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(<yourBaseURL>));
httpClient.DefaultRequestHeaders.Add("Token, <yourToken>);
return httpClient;
}
I know this is and old thread, but I was fighting with this and I would like to share my solution.
This solution works with HttpClient and MultipartFormDataContent, from System.Net.Http. You can release it with .NET Core 1.0 or higher, or .NET Framework 4.5 or higher.
As a quick summary, it's an asynchronous method that receives as parameters the URL in which you want to perform the POST, a key/value collection for sending strings, and a key/value collection for sending files.
private static async Task<HttpResponseMessage> Post(string url, NameValueCollection strings, NameValueCollection files)
{
var formContent = new MultipartFormDataContent(/* If you need a boundary, you can define it here */);
// Strings
foreach (string key in strings.Keys)
{
string inputName = key;
string content = strings[key];
formContent.Add(new StringContent(content), inputName);
}
// Files
foreach (string key in files.Keys)
{
string inputName = key;
string fullPathToFile = files[key];
FileStream fileStream = File.OpenRead(fullPathToFile);
var streamContent = new StreamContent(fileStream);
var fileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
formContent.Add(fileContent, inputName, Path.GetFileName(fullPathToFile));
}
var myHttpClient = new HttpClient();
var response = await myHttpClient.PostAsync(url, formContent);
//string stringContent = await response.Content.ReadAsStringAsync(); // If you need to read the content
return response;
}
You can prepare your POST like this (you can add so many strings and files as you need):
string url = #"http://yoursite.com/upload.php"
NameValueCollection strings = new NameValueCollection();
strings.Add("stringInputName1", "The content for input 1");
strings.Add("stringInputNameN", "The content for input N");
NameValueCollection files = new NameValueCollection();
files.Add("fileInputName1", #"FullPathToFile1"); // Path + filename
files.Add("fileInputNameN", #"FullPathToFileN");
And finally, call the method like this:
var result = Post(url, strings, files).GetAwaiter().GetResult();
If you want, you can check your status code, and show the reason as below:
if (result.StatusCode == HttpStatusCode.OK)
{
// Logic if all was OK
}
else
{
// You can show a message like this:
Console.WriteLine(string.Format("Error. StatusCode: {0} | ReasonPhrase: {1}", result.StatusCode, result.ReasonPhrase));
}
And if someone need it, here I let a small example of how to receive store a file with PHP (at the other side of our .Net app):
<?php
if (isset($_FILES['fileInputName1']) && $_FILES['fileInputName1']['error'] === UPLOAD_ERR_OK)
{
$fileTmpPath = $_FILES['fileInputName1']['tmp_name'];
$fileName = $_FILES['fileInputName1']['name'];
move_uploaded_file($fileTmpPath, '/the/final/path/you/want/' . $fileName);
}
I hope you find it useful, I am attentive to your questions.
The below code reads a file, converts it to a byte array and then makes a request to the server.
public void PostImage()
{
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
byte[] imagebytearraystring = ImageFileToByteArray(#"C:\Users\Downloads\icon.png");
form.Add(new ByteArrayContent(imagebytearraystring, 0, imagebytearraystring.Count()), "profile_pic", "hello1.jpg");
HttpResponseMessage response = httpClient.PostAsync("your url", form).Result;
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
}
private byte[] ImageFileToByteArray(string fullFilePath)
{
FileStream fs = File.OpenRead(fullFilePath);
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
fs.Close();
return bytes;
}
hi guys after one day searching on web finally i solve problem with below source code
hope to help you
public UploadResult UploadFile(string fileAddress)
{
HttpClient client = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new StringContent("fileToUpload");
form.Add(content, "fileToUpload");
var stream = new FileStream(fileAddress, FileMode.Open);
content = new StreamContent(stream);
var fileName =
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "name",
FileName = Path.GetFileName(fileAddress),
};
form.Add(content);
HttpResponseMessage response = null;
var url = new Uri("http://192.168.10.236:2000/api/Upload2");
response = (client.PostAsync(url, form)).Result;
}
Here is multipart data post with basic authentication C#
public string UploadFilesToRemoteUrl(string url)
{
try
{
Dictionary<string, object> formFields = new Dictionary<string, object>();
formFields.Add("requestid", "{\"id\":\"idvalue\"}");
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" + boundary;
// basic authentication.
var username = "userid";
var password = "password";
string credidentials = username + ":" + password;
var authorization = Convert.ToBase64String(Encoding.Default.GetBytes(credidentials));
request.Headers["Authorization"] = "Basic " + authorization;
request.Method = "POST";
request.KeepAlive = true;
Stream memStream = new System.IO.MemoryStream();
WriteFormData(formFields, memStream, boundary);
FileInfo fileToUpload = new FileInfo(#"filelocation with name");
string fileFormKey = "file";
if (fileToUpload != null)
{
WritefileToUpload(fileToUpload, memStream, boundary, fileFormKey);
}
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 responseSReam = response.GetResponseStream();
StreamReader streamReader = new StreamReader(responseSReam);
return streamReader.ReadToEnd();
}
}
catch (WebException ex)
{
using (WebResponse response = ex.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)response;
using (var streamReader = new StreamReader(response.GetResponseStream()))
return streamReader.ReadToEnd();
}
}
}
// write form id.
public static void WriteFormData(Dictionary<string, object> dictionary, Stream stream, string mimeBoundary)
{
string formdataTemplate = "\r\n--" + mimeBoundary +
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
if (dictionary != null)
{
foreach (string key in dictionary.Keys)
{
string formitem = string.Format(formdataTemplate, key, dictionary[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
stream.Write(formitembytes, 0, formitembytes.Length);
}
}
}
// write file.
public static void WritefileToUpload(FileInfo file, Stream stream, string mimeBoundary, string formkey)
{
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "\r\n");
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "--");
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
stream.Write(boundarybytes, 0, boundarybytes.Length);
var header = string.Format(headerTemplate, formkey, file.Name);
var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
stream.Write(headerbytes, 0, headerbytes.Length);
using (var fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
{
var buffer = new byte[1024];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
stream.Write(buffer, 0, bytesRead);
}
}
stream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
}
For people searching for 403 forbidden issue while trying to upload in multipart form the below might help as there is a case depending on the server configuration that you will get MULTIPART_STRICT_ERROR "!#eq 0" due to incorrect MultipartFormDataContent headers.
Please note that both imagetag/filename variables include quotations (\")
eg filename="\"myfile.png\"" .
MultipartFormDataContent form = new MultipartFormDataContent();
ByteArrayContent imageContent = new ByteArrayContent(fileBytes, 0, fileBytes.Length);
imageContent.Headers.TryAddWithoutValidation("Content-Disposition", "form-data; name="+imagetag+"; filename="+filename);
imageContent.Headers.TryAddWithoutValidation("Content-Type", "image / png");
form.Add(imageContent, imagetag, filename);
I was also wanted to upload stuff to a Server and it was a Spring application i finally discovered that I needed to acctually set an content type for it to interpret it as a file. Just like this:
...
MultipartFormDataContent form = new MultipartFormDataContent();
var fileStream = new FileStream(uniqueTempPathInProject, FileMode.Open);
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentType=new MediaTypeHeaderValue("application/zip");
form.Add(streamContent, "file",fileName);
...
I know this is an old post, but after spending an entire afternoon trying, I have to share what worked for me. My solution is for a Xamarin application but the code should still work as long as it is C#:
The issue I had is that I wanted to use the same end-point and payload as my Angular app. (Code Below).
public class ApiService<T> where T : class
{
private string _webServiceUrl = Settings.WebServiceUrl;
private HttpClient httpClient;
public ApiService(string path = null)
{
_webServiceUrl = $"{_webServiceUrl}{path}/";
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(_webServiceUrl);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Settings.Token);
}
private void HandleException(Exception ex, string url = "")
{
Settings.TotalHttpRequests -= 1;
Crashes.TrackError(ex, new Dictionary<string, string>{ { "URL", url }, });
MessagingCenter.Send<Page, string>(new Page(), "Exception", ex.Message);
}
public async Task<T> PostFormDataAsync(string url, string filePath, T t)
{
using (var form = new MultipartFormDataContent())
{
using (var fs = File.OpenRead(filePath))
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
fs.Close();
var json = JsonConvert.SerializeObject(t);
var data = new StringContent(json);
form.Add(new ByteArrayContent(bytes, 0, bytes.Length), "file", fs.Name);
form.Add(data, "data");
Settings.TotalHttpRequests += 1;
var result = await httpClient.PostAsync(url, form);
Settings.TotalHttpRequests -= 1;
if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
var item = JsonConvert.DeserializeObject<T>(content);
return item;
}
else
{
await RaiseErrorAsync(result);
return default(T);
}
}
}
}
private async Task RaiseErrorAsync(HttpResponseMessage result)
{
var message = await result.Content.ReadAsStringAsync();
MessagingCenter.Send<Page, string>(new Page(), "Error", message);
}
}
I have included some code for the benefit of other Xamarin Developers.
My API endpoint is as follows:
[DisableRequestSizeLimit]
[Consumes("multipart/form-data")]
[HttpPost]
public async Task<ActionResult> Post()
{
try
{
var data = (Request.Form["data"]).ToString();
var myObject = JsonConvert.DeserializeObject<MyClass>(data);
var file = Request.Form.Files[0];
myObject = await _service.AddAsync(myObject, file);
var result = _mapper.Map<MyClassDto>(myObject);
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
From this, I get my file as an IFormFile instance. I am also able to deserialize the object I sent as t of type T.
The ApiService can be modified to implement IApiService so that you can benefit from Dependency Service (in Xamarin).
On the Angular side, this is what I have on the component:
onSubmit() {
this.submitted = true;
if (this.form.invalid) {return;}
if (this.fileToUpload == null) {
Swal.fire('File', 'Please attach the file', 'error');
return;
}
const formData = new FormData();
formData.append('file', this.fileToUpload, this.fileToUpload.name);
formData.append('data', JSON.stringify(this.form.value));
this.service.postEndpoint('', formData).subscribe((data) => {
//Do something here
});
}
For the service:
import { ApiService } from '../api.service';
#Injectable({
providedIn: 'root'
})
export class MyService extends ApiService<MyClass>{
constructor(protected httpClient: HttpClient) {
super(httpClient, 'MyApiController');
}
}
The ApiService:
const httpOptions = {
headers : new HttpHeaders({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
};
export abstract class ApiService<T> {
basePath = environment.apiPath;
apiURL = `${this.basePath}api/`;
constructor(protected httpClient: HttpClient, protected actionUrl: string) { }
public postEndpoint(endPoint: string, model: any): Observable<any> {
return this.httpClient.post(this.apiURL + `${this.actionUrl}/${endPoint}`, model, httpOptions);
}
}
I hope this saves someone some time! Happy coding!
It work for window phone 8.1. You can try this.
Dictionary<string, object> _headerContents = new Dictionary<string, object>();
const String _lineEnd = "\r\n";
const String _twoHyphens = "--";
const String _boundary = "*****";
private async void UploadFile_OnTap(object sender, System.Windows.Input.GestureEventArgs e)
{
Uri serverUri = new Uri("http:www.myserver.com/Mp4UploadHandler", UriKind.Absolute);
string fileContentType = "multipart/form-data";
byte[] _boundarybytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _lineEnd);
byte[] _trailerbytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _twoHyphens + _lineEnd);
Dictionary<string, object> _headerContents = new Dictionary<string, object>();
SetEndHeaders(); // to add some extra parameter if you need
httpWebRequest = (HttpWebRequest)WebRequest.Create(serverUri);
httpWebRequest.ContentType = fileContentType + "; boundary=" + _boundary;
httpWebRequest.Method = "POST";
httpWebRequest.AllowWriteStreamBuffering = false; // get response after upload header part
var fileName = Path.GetFileName(MediaStorageFile.Path);
Stream fStream = (await MediaStorageFile.OpenAsync(Windows.Storage.FileAccessMode.Read)).AsStream(); //MediaStorageFile is a storage file from where you want to upload the file of your device
string fileheaderTemplate = "Content-Disposition: form-data; name=\"{0}\"" + _lineEnd + _lineEnd + "{1}" + _lineEnd;
long httpLength = 0;
foreach (var headerContent in _headerContents) // get the length of upload strem
httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes(string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value)).Length;
httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes("Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd).Length
+ Encoding.UTF8.GetBytes(_lineEnd).Length * 2 + _trailerbytes.Length;
httpWebRequest.ContentLength = httpLength + fStream.Length; // wait until you upload your total stream
httpWebRequest.BeginGetRequestStream((result) =>
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream stream = request.EndGetRequestStream(result))
{
foreach (var headerContent in _headerContents)
{
WriteToStream(stream, _boundarybytes);
WriteToStream(stream, string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value));
}
WriteToStream(stream, _boundarybytes);
WriteToStream(stream, "Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd);
WriteToStream(stream, _lineEnd);
int bytesRead = 0;
byte[] buffer = new byte[2048]; //upload 2K each time
while ((bytesRead = fStream.Read(buffer, 0, buffer.Length)) != 0)
{
stream.Write(buffer, 0, bytesRead);
Array.Clear(buffer, 0, 2048); // Clear the array.
}
WriteToStream(stream, _lineEnd);
WriteToStream(stream, _trailerbytes);
fStream.Close();
}
request.BeginGetResponse(a =>
{ //get response here
try
{
var response = request.EndGetResponse(a);
using (Stream streamResponse = response.GetResponseStream())
using (var memoryStream = new MemoryStream())
{
streamResponse.CopyTo(memoryStream);
responseBytes = memoryStream.ToArray(); // here I get byte response from server. you can change depends on server response
}
if (responseBytes.Length > 0 && responseBytes[0] == 1)
MessageBox.Show("Uploading Completed");
else
MessageBox.Show("Uploading failed, please try again.");
}
catch (Exception ex)
{}
}, null);
}
catch (Exception ex)
{
fStream.Close();
}
}, httpWebRequest);
}
private static void WriteToStream(Stream s, string txt)
{
byte[] bytes = Encoding.UTF8.GetBytes(txt);
s.Write(bytes, 0, bytes.Length);
}
private static void WriteToStream(Stream s, byte[] bytes)
{
s.Write(bytes, 0, bytes.Length);
}
private void SetEndHeaders()
{
_headerContents.Add("sId", LocalData.currentUser.SessionId);
_headerContents.Add("uId", LocalData.currentUser.UserIdentity);
_headerContents.Add("authServer", LocalData.currentUser.AuthServerIP);
_headerContents.Add("comPort", LocalData.currentUser.ComPort);
}
Top to #loop answer.
We got below error for Asp.Net MVC,
Unable to connect to the remote server
Fix:
After adding the below code in Web.Confing issue has been resolved for us
<system.net>
<defaultProxy useDefaultCredentials="true" >
</defaultProxy>
</system.net>
Base on #Wolf5 's answer This works for me
var client = new WebClient();
client.Encoding = Encoding.UTF8;
var boundary = $"--------------------------{DateTime.Now.Ticks:x}";
client.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
client.Headers.Add("Cookie", cookie);
var start = $"--{boundary}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{Path.GetFileName(fileName)}\"\r\nContent-Type: image/jpeg\r\n\r\n";
var end = $"\r\n--{boundary}--\r\n";
var lst = new List<byte>();
lst.AddRange(client.Encoding.GetBytes(start));
lst.AddRange(File.ReadAllBytes(fileName));
lst.AddRange(client.Encoding.GetBytes(end));
var resp = client.UploadData($"{ApiUrl}/api/upload/image", "POST", lst.ToArray());

Categories

Resources