Sending binary data along with a REST API request (2024)

Sending binary data along with a REST API request

The problem I would like to discuss is an API call, where you need to send binary data (for example multiple images) and some metadata information together. There are various ways you can approach this, and I will describe them briefly. Then I will go into more detail on multipart/form-data requests and how they can help you with the mentioned task.

Approach 1 – Send metadata and files in separate requests

The steps could be this:

  1. Send metadata to server
  2. Server stores metadata and generates an unique URL, to which files should be uploaded. Sends the URL in response.
  3. Client posts files to specified URL

This may be a good approach in a scenario, where you don’t need to receive the files right away together with the metadata. This enables the client to upload some initial files, then later add some more. This could be a good approach if you are creating a new photo album (metadata), then adding photos to it.

Approach 2 – Send metadata and files together in one request

There are some cases however when metadata and files are one entity and neither makes sense on its own. In this scenario you want to take some action on the whole client request data right away. Let’s say you are creating a service that combines some images into one, calculates some statistics, etc. If you used approach 1 in this scenario, you need to manage state between client requests. This can be complex and may hurt your scalability.

Fortunately you can send all data in one request if this is what makes the most sense. Here are a few ways to do this:

JSON / XML

Probably the easiest and most compatible way to send the data is to serialize it to JSON or XML. Also the binary data, which means getting +33% in message size due to BASE64 compression. This may be just fine in some cases.

BSON

However if the extra message size is not something you can put up with, then you can use a form of binary serialization. With ASP.NET WebAPI 2.1 you’ll get BsonMediaTypeFormatter out of the box, which will help you use BSON serialization (see http://bsonspec.org/). On the client side, you can use JSON.NET to do the serialization of the request message.

With some effort you should also be able to use Google’s protobuf protocol, which may be more efficient according to this blog post.

multipart/form-data

In some cases, maybe for compatibility reasons, you’ll not be able to use modern binary serialization like BSON or protobuf. In those cases you can still avoid sending binary data in BASE64 encoded string. You can use multipart/form-data request, effectively simulating HTML forms with file uploads behavior. This is a bit more complex than the previous approaches, so I would like to go into more detail.

But before that, I should mention, that this approach is not semantically correct. By using the Content-Type multipart/form-data you state, that what you send is actually a form. But it is not. It is rather some custom data format and for that, the most appropriate content type seems to be multipart/mixed (see the RFC). The HttpClient library for .NET won’t have any problems handling different subtypes of multipart/* MIME type, but for other platforms, it may not be true. I have seen some libraries (for Python for example), which had multipart/form-data content type hardcoded. So in this case you have two options: either write your own client library or give up being semantically correct and go with multipart/form-data. I can live with the latter.

So how to put some metadata together with multiple files into one request? Look at this example:

POST http://127.0.0.1:53908/api/send HTTP/1.1
Content-Type: multipart/form-data; boundary="01ead4a5-7a67-4703-ad02-589886e00923"
Host: 127.0.0.1:53908
Content-Length: 707419

--01ead4a5-7a67-4703-ad02-589886e00923
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=imageset

{"name":"Model"}
--01ead4a5-7a67-4703-ad02-589886e00923
Content-Type: image/jpeg
Content-Disposition: form-data; name=image0; filename=Small-Talk-image.jpg


...image content...
--01ead4a5-7a67-4703-ad02-589886e00923
Content-Type: image/jpeg
Content-Disposition: form-data; name=image2; filename=url.jpg

...image content...
--01ead4a5-7a67-4703-ad02-589886e00923--

Going from the top we have a part with name = imageset. This part contains the metadata. It has JSON content type and a serialized JSON object. Then there are two parts containing image data with names image0 and image1. Those two additionally specify: image filename and image type (in Content-Type header).

The server, after receiving such request, can distinguish metadata and image data by looking at the part names (the names are part of the API contract client needs to follow). Then it can put the request together and execute a controller action passing in received data.

So how to actually implement this using ASP.NET WebAPI? (you can look at the code at Github)

Let’s start quickly with the definition of the data passed around:

 public class ImageSet { public string Name { get; set; } public List<Image> Images { get; set; } } public class Image { public string FileName { get; set; } public string MimeType { get; set; } public byte[] ImageData { get; set; } }

Now, when implementing a WebAPI controller, we would like to receive and instance of the ImageSet as a parameter of the action.

[Route("api/send")]public string UploadImageSet(ImageSet model){ var sb = new StringBuilder(); sb.AppendFormat("Received image set {0}: ", model.Name); model.Images.ForEach(i => sb.AppendFormat("Got image {0} of type {1} and size {2} bytes,", i.FileName, i.MimeType, i.ImageData.Length) ); var result = sb.ToString(); Trace.Write(result); return result;}

Fortunately, WebAPI has a notion of MediaTypeFormatter, which basically lets you define logic for translating a certain type of request to a certain .NET type (and back). Here’s how to implement one for the ImageSet:

public class ImageSetMediaTypeFormatter : MediaTypeFormatter{ public ImageSetMediaTypeFormatter() { SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data")); } public override bool CanReadType(Type type) { return type == typeof (ImageSet); } public override bool CanWriteType(Type type) { return false; } public async override Task<object> ReadFromStreamAsync( Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) { var provider = await content.ReadAsMultipartAsync(); var modelContent = provider.Contents .FirstOrDefault(c => c.Headers.ContentDisposition.Name.NormalizeName() == "imageset"); var imageSet = await modelContent.ReadAsAsync<ImageSet>(); var fileContents = provider.Contents .Where(c => c.Headers.ContentDisposition.Name.NormalizeName().Matches(@"image\d+")) .ToList(); imageSet.Images = new List<Image>(); foreach (var fileContent in fileContents) { imageSet.Images.Add(new Image { ImageData = await fileContent.ReadAsByteArrayAsync(), MimeType = fileContent.Headers.ContentType.MediaType, FileName = fileContent.Headers.ContentDisposition.FileName.NormalizeName() }); } return imageSet; }}public static class StringExtenstions{ public static string NormalizeName(this string text) { return text.Replace("\"", ""); } public static bool Matches(this string text, string pattern) { return Regex.IsMatch(text, pattern); }}

By adding an entry to SupportedMediaTypes, you specify what content types this MediaTypeFormatter is able to handle. Then in CanRead and CanWrite you specify .NET types, to which (or from which) the request can be translated. ReadFromStreamAsync does the actual work.

Decoupling controller logic from request parsing logic gives you possibility to handle multiple request formats and you can let your clients choose the format they are most comfortable with by specifying appropriate Content-Type header.

Note: when you do the content.ReadAsMultipartAsync() call, you are using the MultipartMemoryStreamProvider, which handles all processing in-memory. Depending on your scenario, you may take different approach, for example MultipartFormDataStreamProvider, for which you’ll find a nice sample here.

The above code doesn’t do any request format validation for clarity of the example. In production, you’ll get all types of malformed requests from 3rd party clients, so you need to handle those situations.

How about some client code? First of all, on the client side we’ll make a small change in the ImageSet class:

 public class ImageSet { public string Name { get; set; } [JsonIgnore] public List<Image> Images { get; set; } }

We want the JSON serialization to ignore Images collection, since they will be put into separate request parts.

This is how you could prepare a request to be sent:

static void Main(string[] args){ var imageSet = new ImageSet() { Name = "Model", Images = Directory .EnumerateFiles("../../../../../SampleImages") .Where(file => new[] {".jpg", ".png"}.Contains(Path.GetExtension(file))) .Select(file => new Image { FileName = Path.GetFileName(file), MimeType = MimeMapping.GetMimeMapping(file), ImageData = File.ReadAllBytes(file) }) .ToList() }; SendImageSet(imageSet);}

And here’s how to send it using HttpClient and Json .NET:

private static void SendImageSet(ImageSet imageSet){ var multipartContent = new MultipartFormDataContent(); var imageSetJson = JsonConvert.SerializeObject(imageSet, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); multipartContent.Add( new StringContent(imageSetJson, Encoding.UTF8, "application/json"), "imageset" ); int counter = 0; foreach (var image in imageSet.Images) { var imageContent = new ByteArrayContent(image.ImageData); imageContent.Headers.ContentType = new MediaTypeHeaderValue(image.MimeType); multipartContent.Add(imageContent, "image" + counter++, image.FileName); } var response = new HttpClient() .PostAsync("http://localhost:53908/api/send", multipartContent) .Result; var responseContent = response.Content.ReadAsStringAsync().Result; Trace.Write(responseContent);}

Summary

There are multiple ways to send mixed plain text / binary data to a REST API endpoint. The best what you can do while implementing public-facing API, is to let your clients choose format which is convenient for them. ASP.NET WebAPI has ways to facilitate that. multipart/form-data requests are a bit more complicated than whole-request binary serialization (BSON or protobuf), but may be more compatible with some platforms.

The code presented in this post can be found on Github. You’ll find there also client code samples for multipart/form-data scenario for Java, Python and node.js

Sending binary data along with a REST API request (2024)

FAQs

Can we send binary data in JSON? ›

The JSON format natively doesn't support binary data. The binary data has to be escaped so that it can be placed into a string element (i.e. zero or more Unicode chars in double quotes using backslash escapes) in JSON.

Can you send binary data over HTTP? ›

HTTP is perfectly capable of handling binary data: images are sent over HTTP all the time, and they're binary. People upload and download files of arbitrary data types all the time with no problem.

How do you send binary data to the postman? ›

First, set the body to "binary": Select "binary" to have Postman send binary data. Now click "Select File" in Postman to attach a file: Attach a file to upload with the "Select File" button.

Is binary data allowed in GET method? ›

When a GET method returns binary data, the Swagger document that is generated by IBM® Cúram Social Program Management specifies the Response Content type as anything other than application/json. This response indicates that binary content and not JSON content is provided in the response.

What is BSON vs JSON? ›

JSON stands for JavaScript Object Notation. BSON stands for Binary JavaScript Object Notation. JSON data contains its data basic in JSON format. BSON gives extra datatypes over the JSON data.

Why do we use binary encoding? ›

Binary encoding is a procedure to convert data to a form that is easily used by difference computer operating systems. This achieved by converting binary data to a ASCII string format, specifically, converting 8-bit data into a 7-bit format, that use as standard set of ASCII printable characters.

Is multipart form data binary? ›

The message part header must specify any encoding other than the default (7BIT). Multipart/form-data is ideal for sending non-ASCII or binary data, and is the only content type that allows you to upload files.

Is HTTP a binary? ›

Binary framing layer #

x protocol, all HTTP/2 communication is split into smaller messages and frames, each of which is encoded in binary format. As a result, both client and server must use the new binary encoding mechanism to understand each other: an HTTP/1.

What is raw binary data? ›

A binary file (with the extension . rbf) containing configuration data for use outside the Quartus® Prime software. A Raw Binary File contains the binary equivalent of a Tabular Text File (. ttf).

What is binary format in Postman? ›

Postman allows to set the body in a text based format (plain text, JSON, XML, etc) or as a binary file. If you try to copy binary data into the text box it will probably be corrupted. It is best to have the binary data in a file and attach the file. Follow this answer to receive notifications.

How do I receive files in REST API? ›

To attach a file, you must include it with the Body as form-data. Once you are in the Body → form-data fields, you must enter a KEY . This should be “file” or whichever value you specified in the @RequestPart(“[value]”) . After doing so, a dropdown will appear that gives you the option of Text or File.

How do I send raw data to my Postman? ›

You can use raw body data to send anything you can enter as text. Use the raw tab, and the type dropdown list to indicate the format of your data (Text, JavaScript, JSON, HTML, or XML) and Postman will enable syntax-highlighting as well as appending the relevant headers to your request.

What is difference between GET and POST method in REST API? ›

1. GET retrieves a representation of the specified resource. POST is for writing data, to be processed to the identified resource.

How do I add binary media type API gateway? ›

Under the selected API in the primary navigation panel, choose Settings. In the Settings pane, choose Add Binary Media Type in the Binary Media Types section. Type a required media type, for example, image/png , in the input text field. If needed, repeat this step to add more media types.

What is the difference between binary and source code? ›

A source code scanner analyzes un-compiled code, whereas a binary scanner analyzes compiled code, but in the end, the result is the same. They are simply two engineering solutions for the same problem.

Why BSON is faster than JSON? ›

BSON is also designed in a way that it has a comparatively faster encoding and decoding technique. For example, all those integers stored as 32-bit integers so that they are not parsed with them to and from the text. Therefore, it uses more space than JSON for smaller integers, but BSON is anyway much faster to parse.

What are some reasons for using BSON over JSON? ›

BSON is designed as a binary representation of JSON data, with specific extensions for broader applications, and optimized for data storage and retrieval. One particular way in which BSON differs from JSON is in its support for some more advanced types of data.

Which is better XML or JSON? ›

JSON is simpler than XML, but XML is more powerful. For common applications, JSON's terse semantics result in code that is easier to follow. For applications with complex requirements surrounding data interchange, such as in enterprise, the powerful features of XML can significantly reduce software risk.

How do you use binary encoding? ›

Binary encoding uses the binary digit, or bit, as the fundamental unit of information, and a bit may only be a '0' or a '1' (only two possibilities since it is a binary-encoded system). By combining bits, numbers larger than 0 or 1 may be represented, and these bit collections are called words.

How is binary data stored? ›

Binary data is primarily stored on the hard disk drive (HDD). The device is made up of a spinning disk (or disks) with magnetic coatings and heads that can both read and write information in the form of magnetic patterns. In addition to hard disk drives, floppy disks and tapes also store data magnetically.

Why is data stored in binary? ›

Computer systems are designed to process data. In order to do so, computers use electronic circuits that function as switches that can be turned on or off. We use a binary form to represent these two states: A 0 represents when a switch is off.

What is multi part binary input? ›

It means we can attach multiple files with POST method. 19th July 2016, 12:26 AM. Preeti Srivastava. +2. use enctype attribute in form tag with multi-part binary input to work with files like audio,video,images etc.

What is multipart form data in REST API? ›

The multipart mime format is used to pass lists of content bodies. Multiple content bodies are embedded in one message. multipart/form-data is often found in web application HTML Form documents and is generally used to upload files.

How do I encode a multipart form data? ›

Multipart form data: The ENCTYPE attribute of <form> tag specifies the method of encoding for the form data. It is one of the two ways of encoding the HTML form. It is specifically used when file uploading is required in HTML form. It sends the form data to server in multiple parts because of large size of file.

Why is HTTP not binary? ›

HTTP defines a way to work with resources . These resources do not need to be text, they can be images, or anything else. A text resource can be sent as binary by specifying the Content-Encoding header. Your resource type is specified via the Content-Type header.

What is a binary protocol? ›

Binary. A binary protocol utilizes all values of a byte, as opposed to a text-based protocol which only uses values corresponding to human-readable characters in ASCII encoding. Binary protocols are intended to be read by a machine rather than a human being.

What is BLOB data type? ›

A BLOB (binary large object) is a varying-length binary string that can be up to 2,147,483,647 characters long. Like other binary types, BLOB strings are not associated with a code page. In addition, BLOB strings do not hold character data.

How do you process binary data? ›

You can choose one of two methods for loading the data. 1) Use the commands open file, read from file and close file. 2) Use the URL keyword with the put command, prefixing the file path with "binfile:". Either approach allows you to place binary data into a variable so that it can be processed.

What is an example of binary data? ›

Some examples of binary variables, i.e. attributes, are: Smoking is a binary variable with only two possible values: yes or no. A medical test has two possible outcomes: positive or negative. Gender is traditionally described as male or female.

What does binary data look like? ›

Structure. Binary files are usually thought of as being a sequence of bytes, which means the binary digits (bits) are grouped in eights. Binary files typically contain bytes that are intended to be interpreted as something other than text characters.

How do I send a POST request to Rest API? ›

Use an HTTP POST request to send single or multiple RPC requests to the REST API.
...
For both single and multiple RPC commands, HTTP Accept headers can be used to specify the return format using one of the following Content-Type values:
  1. application/xml (the default)
  2. application/json.
  3. text/plain.
  4. text/html.

How do I give JSON data to Postman? ›

In Postman, change the method next to the URL to 'POST', and under the 'Body' tab choose the 'raw' radio button and then 'JSON (application/json)' from the drop down. You can now type in the JSON you want to send along with the POST request. If this is successful, you should see the new data in your 'db. json' file.

How do you pass multiple query parameters in Postman? ›

Enter the same URL in the Postman text field; you will get the multiple parameters in the Params tab. Even you can write each of the parameters and send a request with multiple parameters.

Can we send file in REST API? ›

Use the File transfer REST API to upload and download files using HTTP or HTTPS as the transport protocol and to list the contents of a directory. Uploads a file to any back-end application that supports REST APIs over HTTP or HTTPS protocol.

How do I send files over API? ›

  1. Add the file's data to the request body.
  2. Add these HTTP headers: Content-Type . Set to the MIME media type of the object being uploaded. Content-Length . Set to the number of bytes you upload. ...
  3. Send the request. If the request succeeds, the server returns the HTTP 200 OK status code along with the file's metadata.

Can we upload file using REST API? ›

You can use this parameter to set metadata values to a collection already assigned to any parent folder. The rules are the same as those applied to the set metadata values REST API. Use Content-Type: application/json to describe this information as a JSON object. File to upload.

How do you send encrypted data in REST API Postman? ›

You can use the CryptoJs library of the postman to convert string data to AES encrypted data. const encryptedText = CryptoJS. AES. encrypt('message', 'secret').

How do I send a payload in a POST request? ›

Sending a payload

post("https://restful-booker.herokuapp.com/auth"); String authResponse = response. getBody(). print(); assertThat(authResponse, containsString("token")); So we begin by calling AuthPayload to create a new Java Object with the values we want to send in the HTTP POST request.

How do I POST JSON to a REST API endpoint? ›

To post JSON to a REST API endpoint, you must send an HTTP POST request to the REST API server and provide JSON data in the body of the POST message. You also need to specify the data type in the body of the POST message using the Content-Type: application/json request header.

What are the methods in REST API? ›

The 5 essential HTTP methods in RESTful API development
  • HTTP resources vs. resource collections. ...
  • Method 1: POST. POST is the only RESTful API HTTP method that primarily operates on resource collections. ...
  • Method 2: PUT. ...
  • Method 3: PATCH. ...
  • Method 4: GET. ...
  • Method 5: DELETE.
Jul 16, 2021

How do you know if a request is GET or POST? ›

“check if request method is post or get in php” Code Answer
  1. if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  2. // Boom baby we a POST method.
  3. }
  4. if ($_SERVER['REQUEST_METHOD'] === 'GET') {
  5. // We are a GET method.
  6. }

Should I use put or POST? ›

Use PUT when you want to modify a single resource which is already a part of resources collection. PUT overwrites the resource in its entirety. Use PATCH if request updates part of the resource. Use POST when you want to add a child resource under resources collection.

What is binary payload? ›

A binary payload is a set of binary files, configuration files, batch, or Shell scripts. Binary payload deployment refers to the deployment of a custom binary payload across environments. Starting with BMC Remedy AR System 9.1.04, BMC provides all the hotfixes and patches in the binary payload format.

What are binary media types? ›

Example binary media types include image/png or application/octet-stream . You can use the wildcard character ( * ) to cover multiple media types. For example, */* includes all content types. For example code, see Return binary media from a Lambda proxy integration.

What is API gateway payload? ›

API Gateway supports a reasonable payload size limit of 10MB. One way to work within this limit, but still offer a means of importing large datasets to your backend, is to allow uploads through S3. This article shows how to use AWS Lambda to expose an S3 signed URL in response to an API Gateway request.

Is Base64 safe for JSON? ›

Base64 is a safe encoding for JSON. The downside to using Base64 is that it's quite verbose. It can add significant overhead to your file upload which means longer upload and more bandwidth used.

What are JSON data types? ›

JSON Data Types
  • a string.
  • a number.
  • an object (JSON object)
  • an array.
  • a boolean.
  • null.

What is a BSON file? ›

BSON stands for Binary Javascript Object Notation. It is a binary-encoded serialization of JSON documents. BSON has been extended to add some optional non-JSON-native data types, like dates and binary data.

What is JSON format? ›

JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax. It is commonly used for transmitting data in web applications (e.g., sending some data from the server to the client, so it can be displayed on a web page, or vice versa).

Top Articles
Latest Posts
Article information

Author: Prof. Nancy Dach

Last Updated:

Views: 6340

Rating: 4.7 / 5 (77 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Prof. Nancy Dach

Birthday: 1993-08-23

Address: 569 Waelchi Ports, South Blainebury, LA 11589

Phone: +9958996486049

Job: Sales Manager

Hobby: Web surfing, Scuba diving, Mountaineering, Writing, Sailing, Dance, Blacksmithing

Introduction: My name is Prof. Nancy Dach, I am a lively, joyous, courageous, lovely, tender, charming, open person who loves writing and wants to share my knowledge and understanding with you.