Post Byte Array to Web API Server Using Httpclient

Post byte array to Web API server using HttpClient

WebAPI v2.1 and beyond supports BSON (Binary JSON) out of the box, and even has a MediaTypeFormatter included for it. This means you can post your entire message in binary format.

If you want to use it, you'll need to set it in WebApiConfig:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Formatters.Add(new BsonMediaTypeFormatter());
}
}

Now, you an use the same BsonMediaTypeFormatter at the client side to serialize your request:

public async Task SendRequestAsync()
{
var client = new HttpClient
{
BaseAddress = new Uri("http://www.yourserviceaddress.com");
};

// Set the Accept header for BSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));

var request = new SomePostRequest
{
Id = 20,
Content = new byte[] { 2, 5, 7, 10 }
};

// POST using the BSON formatter.
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync("api/SomeData/Incoming", request, bsonFormatter);

result.EnsureSuccessStatusCode();
}

Or, you can use Json.NET to serialize your class to BSON. Then, specify you want to use "application/bson" as your "Content-Type":

public async Task SendRequestAsync()
{
using (var stream = new MemoryStream())
using (var bson = new BsonWriter(stream))
{
var jsonSerializer = new JsonSerializer();

var request = new SomePostRequest
{
Id = 20,
Content = new byte[] { 2, 5, 7, 10 }
};

jsonSerializer.Serialize(bson, request);

var client = new HttpClient
{
BaseAddress = new Uri("http://www.yourservicelocation.com")
};

client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));

var byteArrayContent = new ByteArrayContent(stream.ToArray());
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/bson");

var result = await client.PostAsync(
"api/SomeData/Incoming", byteArrayContent);

result.EnsureSuccessStatusCode();
}
}

.NET Core HttpClient upload byte array gives unsupported media type error

While byte[] would be a great way to represent application/octet-stream data, this is not the case by default in asp.net core Web API.

Here is a simple workaround:

Send request by HttpClient:

using var client = new HttpClient() { BaseAddress = new Uri("http://localhost:62033") };
var body = new ByteArrayContent(new byte[] { 1, 2, 3 });
body.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
var result = await client.PostAsync("api/Values/content?someField=someData", body);

Receive action in Web Api project:

[HttpPost("content")]
public IActionResult Upload([FromBody]byte[] documentData, [FromQuery] string someField)
{
return Ok();
}

Custom InputFormatter in Web Api Project:

public class ByteArrayInputFormatter : InputFormatter
{
public ByteArrayInputFormatter()
{
SupportedMediaTypes.Add(Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/octet-stream"));
}

protected override bool CanReadType(Type type)
{
return type == typeof(byte[]);
}

public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var stream = new MemoryStream();
await context.HttpContext.Request.Body.CopyToAsync(stream);
return InputFormatterResult.SuccessAsync(stream.ToArray());
}
}

Startup.cs in Web Api Project:

services.AddControllers(options=> 
options.InputFormatters.Add(new ByteArrayInputFormatter()));

Result:

Sample Image

send byte array by HTTP POST in store app

It will be more straightforward to use System.Net.Http.ByteArrayContent. E.g:

// Converting byte[] into System.Net.Http.HttpContent.
byte[] data = new byte[] { 1, 2, 3, 4, 5};
ByteArrayContent byteContent = new ByteArrayContent(data);
HttpResponseMessage reponse = await client.PostAsync(uri, byteContent);

For text only with an specific text encoding use:

// Convert string into System.Net.Http.HttpContent using UTF-8 encoding.
StringContent stringContent = new StringContent(
"blah blah",
System.Text.Encoding.UTF8);
HttpResponseMessage reponse = await client.PostAsync(uri, stringContent);

Or as you mentioned above, for text and images using multipart/form-data:

// Send binary data and string data in a single request.
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
multipartContent.Add(byteContent);
multipartContent.Add(stringContent);
HttpResponseMessage reponse = await client.PostAsync(uri, multipartContent);

How to Get byte array properly from an Web Api Method in C#?

HTTP is a text based protocol. edit: HTTP can transport raw bytes as well. Luaan's answer is better.

The returned byte array will be converted into text in some way, depending on how the MediaTypeFormatterCollection is set up on the server and on the format requested by the HTTP client with the Accept header. The bytes will typically be converted to text by base64-encoding. The response may also be packaged further into JSON or XML, but the ratio of the expected length (528) to the actual length (706) seems to indicate a simple base64 string.

On the client side, you are not looking at the original bytes but at the bytes of this text representation. I would try reading the data as a string with ReadAsStringAsync and inspect it to see what format it is in. Also look at the headers of the response.

You should then parse this text accordingly to get the original bytes, e.g. with Convert.FromBase64String.

sending binary file byte array to web api method

According to me, it would be easy to use base64 encoding for
communication.

If you want to do so

First, convert your file to byte[] and then to base64 string

Like this:

byte[] bytes = File.ReadAllBytes("path");
string file = Convert.ToBase64String(bytes);
// You have base64 Data in "file" variable

On your WebAPI Endpoint accept string

[HttpPost]
public HttpResponseMessage filewriter(string fileData)
{
}

Then convert your base64 string back to byte[] and write it to file or whatever you want to do with that.

Like This:

// put your base64 string in b64str
Byte[] bytes = Convert.FromBase64String(b64Str);
File.WriteAllBytes(path, bytes);

And you can Compress your string Using GZIP Like this

public static void CopyTo(Stream src, Stream dest) {
byte[] bytes = new byte[4096];

int cnt;

while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) {
dest.Write(bytes, 0, cnt);
}
}

public static byte[] Zip(string str) {
var bytes = Encoding.UTF8.GetBytes(str);

using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
//msi.CopyTo(gs);
CopyTo(msi, gs);
}

return mso.ToArray();
}
}

public static string Unzip(byte[] bytes) {
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
//gs.CopyTo(mso);
CopyTo(gs, mso);
}

return Encoding.UTF8.GetString(mso.ToArray());
}
}

Reference:-

Convert file to base64 and back

GZip Compression



Related Topics



Leave a reply



Submit