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:
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
Restsharp Post Request - Body With X-Www-Form-Urlencoded Values
How to Test If a Instance of a Class Is a Specific Generic Type
Error: the Entity Type Requires a Primary Key
How to Authenticate a Webclient Request
Itextsharp Pdfptable How to Make a Border Around Entire Table
C# Download Big File from Server With Less Memory Consumption
How to Refresh an Entity Framework Core Dbcontext
How to Show a Console Output/Window in a Forms Application
How to Use a Nuget Package Within a Powershell Script
Get Properties and Values from Unknown Object
How to Check If Data Exists Before Writing to Table
Convert Json File to C# and Stored in Database
Convert from Httpresponsemessage to Iactionresult in .Net Core
How to Prevent the Print Progress Dialog Appearing When Performing a Print Preview
How to Make Xmlserializer Ignore the Namespace on Deserialization
How to Show Alert Message in MVC 4 Controller