Binary attachments and downloads

Some responses that the Oda web app receives carry bytes rather than JSON alone: a file's contents coming down to the page, an image, any result that is binary. Such a response arrives as a multipart response, with one part carrying the JSON envelope and further parts carrying the bytes, which are put back into the result at the places the envelope marks. This page is the reference for that framing: the parts, the rules a valid response obeys, and how a malformed or interrupted response fails. For files going the other way, from the page to Oda, see File uploads in the web app.

How a binary response is framed

Each entry of the attachment table names three things:

FieldWhat it names
pathWhere the bytes belong in the result.
codecHow the bytes are coded; the value for these attachments is bytes.
partThe part that carries this entry's bytes.

Where the bytes land in the result

What the page receives

When a binary response fails

Questions, answered

Why did a download fail with invalid binary response?

The multipart response was malformed for one of the reasons in When a binary response fails: a missing, repeated or unclaimed part; metadata or an entry that could not be read; an occupied placeholder; or repeated or overlapping paths. No result was delivered. Ask again, and keep the message for your administrator if it returns.

What is a result-relative path?

The route to a place inside the result: property names, array indices, and any nesting of the two. An empty path means the whole result is the bytes. The attachment table rides beside the result, so no field name is reserved; a path simply points at where the bytes sit.

Why must a placeholder be null?

The bytes are put into the result at the places the table names, and each of those places must be marked with null first. A place that already holds a value is refused instead of overwritten, so the bytes never quietly replace data that was already there.

Can one response carry several values of bytes?

Yes. Each attachment gets its own entry and its own part, named in sequence under bytes-N. The paths must stay unique and must not overlap, so every part lands in its own place.

Do the bytes arrive as text?

No. Every byte place ends up holding a Uint8Array of raw bytes, backed by an ArrayBuffer. Nothing is turned into text on the way, and the JSON values around the bytes are unchanged.

Why did a call fail with rpcId mismatch?

The response carried a different call id than the request sent, so it was not delivered. Every request carries a call id, and its response must echo the same one. Ask again; if the message returns, keep it for your administrator.

What happens if the response is cut off part way?

The call fails, and no short answer is delivered: the response must arrive whole. Bytes that keep arriving after the caller has cancelled fail the call in the same way.

Does compression make a difference to the bytes?

No. The same byte parts are restored whether or not a response is compressed; gzip does not alter the bytes.

Where in the result can bytes sit?

Anywhere a value can: a top-level field, a field nested in others, an item of an array, or the whole result under an empty path. The framing reserves no field names, so the result keeps its own shape.

What does the codec field say?

Each entry declares how its bytes are coded, and the codec for these attachments is bytes: the part carries the raw bytes themselves. An entry that does not declare a valid codec makes the response invalid.