How to send binary data over http, the right way? - c#

I have the following code in C# that converts a string from one encoding to the other and send the response over http.
Everything in the code works fine. I'm just a bit confused 👇
When I return this over http it gets converted into a text representation. I thought this would just send the raw byte array?
Why is it converted? Should I never try and send a raw byte array or is there a case for that when communicating over http? Or is a text representation and a application/octet-stream the way to send binary data over http?
byte[] fromBytes = fromEncoding.GetBytes(body);
byte[] toBytes = Encoding.Convert(fromEncoding, toEncoding, fromBytes);
var response = req.CreateResponse(HttpStatusCode.OK);
MemoryStream ms = new MemoryStream(toBytes);
response.Content = new StreamContent(ms);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return response;

Related

C# Get Byte Array from HTTPResposeMessage

I have an API that returns a PDF file as a byte array:
HttpResponseMessage fileResponse = new HttpResponseMessage
{
Content = new ByteArrayContent(report) //here the byte array is >80000 in length
};
fileResponse.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
return fileResponse;
On the client, I have:
HttpResponseMessage result = null;
using (HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
result = await client.GetAsync(getFileURL);
}
Byte[] bytes = response.Content.ReadAsByteArrayAsync().Result;
This code worked until an upgrade to .Net 5.
Now bytes is only <350 in length. I have tried converting it from a base64 string as I have read in other solutions, but that throws an error saying it is not a valid base64 string:
string base = response.Content.ReadAsStringAsync().Result.Replace("\"", string.Empty);
byte[] byte = Convert.FromBase64String(base);
Here's what base looks like after the replace, which the next line says is not a valid base64 string. Looks like json but no byte array:
{version:{major:1,minor:1,build:-1,revision:-1,majorRevision:-1,minorRevision:-1},content:{headers:[{key:Content-Type,value:[application/pdf]}]},statusCode:200,reasonPhrase:OK,headers:[],trailingHeaders:[],requestMessage:null,isSuccessStatusCode:true}
So any ideas on how to get the byte array out the response?
The solution I got to work was instead of having the API return an HttpResponseMessage, have it return the byte array directly.
Then in the client converting it from a base64 string gave me the correct byte array that I was able to write as the PDF.

How to handle png from rest api?

Right now, I'm creating a WCF service that sends a location to the Bing Map API and returns a PNG image to the service client. Currently, I copied a working api example from their documentation webpage, and I'm having a hard time figuring out how I can pass it on.
From other stackoverflow questions, I started by converting the response, and I got it into Base64. But it triggered and received an error, that says input is not in Base64 form.
A screenshot of what input looks like
public string getResponse()
{
string key = [My Api Key];
Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}", query, key));
Uri imageryRequest = new Uri(string.Format("https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/Redmond Washington?ms=500,270&zl=12&&c=en-US&he=1&key={0}", key));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imageryRequest);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//Handling the response in PNG
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string input = reader.ReadToEnd();
byte[] data = convert.FromBase64String(input);
return data;
}
It already is a PNG image as byte[]. Also, keep in mind that the image returned is not guaranteed to be PNG, JPEG, or GIF. It returns what it feels is the most appropriate image type unless a specific type is requested.
ex. fmt=jpeg
You just need to do something with it. In my example, I saved it to a file. You probably just need to return the byte[].
private static HttpClient client = new HttpClient();
public static async void GetResponse()
{
string key = Properties.Settings.Default.Key;
Uri imgUri = new Uri($"https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/Redmond Washington?ms=500,270&zl=12&&c=en-US&he=1&fmt=png&key={key}");
HttpResponseMessage response = await client.GetAsync(imgUri);
response.EnsureSuccessStatusCode();
byte[] responseData = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("test.png", responseData);
}

Byte array different from an Web Api Method in C#?

So I have a web api which returns a byte array like this
public byte[] Validate()
{
byte[] buffer = licensePackage.ToByteArray();
return buffer;
}
The thing is when I get it on client it is different size and different byte array, I googled and found this link helpful http://www.codeproject.com/Questions/778483/How-to-Get-byte-array-properly-from-an-Web-Api-Met.
But can I know why this happens? Also, what is an alternate way to send back that file contents from the server?
With the given information I think it must have something to do with content negotiation. I can't tell the reason, but what I'm sure it's that there is a different approach to serve files behind a Web Api.
var response = Request.CreateResponse(HttpStatusCode.OK);
var stream = new FileStream(pathToFile, FileMode.Open, FileAccess.Read);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return ResponseMessage(response);
With this solution, you serve the file contents returning an IHttpActionResult instance. And, returning a response with StreamContent you are returning a stream that must not be modified by Web Api Content Negotation.

Send Bytes From .net desktop application to website

Is there any way to send data (string , files ,,,) In the form of bytes from desktop application to website
You can use the WebClient class to send data in an HTTP request. A string; example:
string url = "http://website.com/MyController/MyAction";
string data = "Something";
string response;
using WebClient client = new WebClient()) {
client.Encoding = Encoding.UTF8;
response = client.UploadString(url, data);
}
Or a byte array; example:
string url = "http://website.com/MyController/MyAction";
byte[] data = { 1, 2, 3 };
byte[] response;
using WebClient client = new WebClient()) {
response = client.UploadData(url, data);
}
In the web application (assuming that you are using MVC and C#) you would have an action method in a controller that gets the data. Example:
public ActionResult MyAction() {
byte[] data = Request.BinaryRead(Request.ContentLength);
// do something with the data
// create a byte array "response" with something to send back
return Content(response, "text/plain");
}
Both a string and a byte array ends up as a byte array when sent, so you would use Encoding.UTF8.GetString(data) to turn the data into the string sent by UploadString.
To return a string for UploadString you would use Encoding.GetBytes(str) to turn a string into bytes.
There are several overloads of those methods that do similar things, that might fit your needs better, but this should get you started.

ISO-8859 encode post request content C#

I am trying to send a POST request in C# with a parameter encoded to ISO-8859. I am using this code:
using (var wb = new WebClient())
{
var encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
var encodedText = System.Web.HttpUtility.UrlEncode("åæ ÆÆ øØ ø", encoding);
wb.Encoding = encoding;
wb.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var data = new NameValueCollection();
data["TXT"] = encodedText;
var response = wb.UploadValues(_url, "POST", data);
}
I have figured out that the correctly encoded string for "åæ ÆÆ øØ ø" is %E5%E6+%C6%C6++%F8%D8+%F8, and I can see when debugging that encodedText actually is this string. However when inspecting the raw request in fiddler, I can see that the string looks like this: TXT=%25e5%25e6%2B%25c6%25c6%2B%25f8%25d8%2B%25f8. I am guessing some kind of extra encoding is being done to the string after or during the call to UploadValues().
Thank you so much in advance.
I checked Google for this. According to another question here on SO at UTF32 for WebClient.UploadValues? (second answer), Webclient.UploadValues() indeed does encoding itself. However, it does ASCII encoding. Youll have to use another method to upload this, like HttpWebRequest.

Categories