Skip to main content
iVentureTeam

binary

The default upload and download control for every binary field in Odoo. Its behavior is simple; the filename wiring around it is where implementations go wrong.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 12, 2026Updated August 12, 20267 min read
Odoo 19 form view showing a binary field rendered by the binary widget with its upload button, the stored file name, and the download and clear controls beside it.
Studio nameFile
Technical namebinary
Field typesbinary
Viewsform, list
Also registered aslist.binary, a compact variant for list view cells
Moduleweb, present in every Odoo database
Used in core15 explicit occurrences across 12 modules, including certificate, l10n_es_edi_tbai, l10n_hu_edi, l10n_eg_edi_eta, cloud_storage_google, plus every binary field with no widget named
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupYes, via Odoo Studio (Enterprise)
Alternativesimage, pdf_viewer, many2many_binary, Char with a URL

What the File field does

Any binary field that does not pick a specialized widget such as image or pdf_viewer renders through this one. Empty, it offers an upload button that opens the file picker. Filled, it shows the file's name with download and clear controls. The upload reads the file in the browser and stores it on the record as base64; the download streams it back through Odoo's /web/content controller, or straight from memory when the file was just uploaded and the record is not saved yet.

Its heavy users in core are the localization and compliance modules, where signed XML files, government submissions and certificates are stored on records: Spanish TicketBAI, Hungarian EDI, Egyptian ETA. Which is fitting, because those are exactly the files nobody can afford to lose to a mislabeled download.

What this means for your team

The binary widget itself never causes project pain. The filename does. A binary column in the database stores bytes, not a name, so Odoo keeps the name in a second char field, and the two are only connected when the view says so. Skip that wiring and your users download files called document with no extension, or stare at a field that reads 108.55 Kb where a contract name should be.

For a team evaluating whether files belong on records at all: single file per record with a known meaning, like a signed contract on a subscription or a submission receipt on an invoice, is what this widget is for. Piles of loosely related documents belong in the chatter's attachments or a many2many_binary field instead, where each file keeps its own identity. Deciding that boundary early keeps document handling from sprawling across half your models.

Setting it up in Odoo Studio (no code)

Odoo Studio (Enterprise) creates the whole arrangement correctly.

  1. Open the form in Studio.

  2. Drag a File field from the Add a field panel onto the form. Studio creates the binary field and handles the filename wiring for you.

  3. In Properties, you can switch the Widget to Image, PDF Viewer or Sign if the file has a known type; the plain File widget is this page's widget.

  4. Set Required or conditional visibility as needed, like any field.

What Studio cannot do here

Studio covers creating the field. The restrictions live in XML:

Limiting what can be picked takes options="{'accepted_file_extensions': '.pdf,.xml'}". There is no Studio control for it.

Enforcing the type takes allowed_mime_type, and even that is a browser side check, not validation. A hard guarantee needs a server side constraint on the model, which is developer work.

Wiring a filename onto an existing hand built field means adding the companion char field and the filename attribute in the view. Studio only does this automatically for fields it created itself.

Supported options in Odoo 19

Verified against binary_field.js in the Odoo 19.0 web module. Two options, one critical attribute, and the attribute is the one everybody forgets.

OptionTypeWhat it does
accepted_file_extensionsstringComma separated extension list fed to the file picker's accept filter, like '.pdf,.xml'. Purely a picker convenience: it does not validate what actually arrives, and defaults to all files.(default: *)
allowed_mime_typestringComma separated MIME whitelist checked at selection time. Files whose type is not in the list are refused with a danger notification naming the file. Client side only; server side enforcement needs a model constraint.(since Odoo 19.0)

The filename is an attribute, not an option. filename="file_name_field" on the field node names the char field that stores the name. Both checks are client side conveniences: accepted_file_extensions only filters the picker dialog, and allowed_mime_type rejects files at selection time with a notification. Neither stops an API import or a determined user, so compliance grade restrictions belong on the server.

Working examples

The canonical pair: binary plus filename

<field name="contract_file" widget="binary" filename="contract_filename"/>
<field name="contract_filename" invisible="1"/>

The second line matters: the filename field must be present in the view, invisible is fine, or the name cannot be saved on upload.

The model side of that pair

contract_file = fields.Binary(string="Contract")
contract_filename = fields.Char(string="Contract Filename")

Restricting the picker to PDFs and XML

<field name="edi_file"
       filename="edi_filename"
       options="{'accepted_file_extensions': '.pdf,.xml', 'allowed_mime_type': 'application/pdf,text/xml'}"/>

The filename machinery, explained once

Why you see "108.55 Kb" instead of a name. When no filename attribute is set, the widget's display falls back to the field's own value when that value is a string. For a saved record, Odoo does not send the binary content to list and form reads, it sends a human readable size placeholder, and that placeholder is what gets displayed and even used as the download name. Every report of "my field shows a file size instead of the file" traces back to this fallback.

The silent filename drop. On upload, the widget writes the file's name into the companion field only if that field exists among the record's loaded fields, meaning it is present somewhere in the view. A correct filename attribute pointing at a real model field still loses the name silently when the field was never added to the arch. The invisible line in the example above is the fix.

The 255 byte cap. The source defines MAX_FILENAME_SIZE_BYTES = 0xFF, matching the filename limit of Linux, Windows and macOS filesystems, and slices the displayed name accordingly, with the comparison done at base64 length. Absurdly long names are truncated for display rather than rejected.

Downloads pick their source. getDownloadData checks whether the current value is a real payload or the size placeholder: fresh uploads on unsaved records download from the in memory base64, saved records stream from the server. That is why a just uploaded file downloads fine before you ever hit Save.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Adds use_replace_button on the development branch; core behavior unchanged. Details below.
Odoo 19.0VerifiedVerified against the shipped source. allowed_mime_type is new in this version.
Odoo 18.0VerifiedSame behavior and filename wiring. accepted_file_extensions only; no allowed_mime_type.

Upgrade note for 18 to 19. Views carry over unchanged. The single addition is the allowed_mime_type option, which did not exist in 18, so it simply becomes available after the upgrade. If a view written for 19 is backported to 18, that option is ignored.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. These findings are read from the public development branch, which can change until feature freeze, and this page will be re-verified against the release.

One new option appears: use_replace_button. With it enabled and no filename available, the widget suppresses the raw value fallback, so instead of the 108.55 Kb placeholder users get a clean replace affordance. It is an opt in fix for exactly the fallback quirk described in the deep dive.

Everything else is cosmetic or internal: props declarations migrate to the new schema system, and the behavior of uploads, downloads, the filename cap and both existing options is unchanged in the diff.

If your Odoo 18 or 19 views lean on binary fields for compliance documents, an upgrade assessment can confirm none of your filename wiring breaks in the jump.

Common problems and fixes

SymptomCause and fix
Field displays a size like 108.55 Kb instead of the file nameNo filename attribute is set, so the widget falls back to the stored value, which is the server's size placeholder. Add a companion char field and wire it with filename="..." on the binary field.
Uploads work but the file name is never savedThe filename attribute points at a field that is not loaded in the view. Add the companion field to the arch, invisible="1" is enough.
Downloaded file has no extension or a generic nameSame missing filename wiring; the download name comes from the companion field. Wire the filename attribute and re-upload, or fill the name field manually.
Users can still pick the wrong file typeaccepted_file_extensions only filters the picker dialog and can be bypassed with All Files. Add allowed_mime_type for a client side rejection, and a server constraint for a real guarantee.
A wrong type import via API was acceptedBoth options are browser side conveniences; the ORM does not check them. Enforce with a Python constraint on the model.
Very long file names appear cut offDisplayed names are capped at 255 bytes, matching filesystem limits. Expected behavior; the stored binary is unaffected.

File field vs the alternatives

WidgetBest forKey difference
binaryOne file of any type per recordPlain upload and download, no preview
imagePictures that should display on the recordRenders the image with resized variants instead of a name link
pdf_viewerPDFs users read in placeEmbeds a browsable PDF preview in the form
many2many_binarySeveral files on one recordAttachment based multi upload instead of one binary column
Char with a URLFiles hosted outside OdooStores a link only, nothing in the database

Pick by file type knowledge: when you know it is an image or a PDF, the specialized widgets add previewing; when files arrive in bundles, move to the attachment based widgets instead of multiplying binary columns.

Frequently asked questions

How do I show the real file name on an Odoo binary field?+
Create a companion char field on the model and reference it from the view with the filename attribute: <field name="file" filename="file_name"/>. The companion field must also be present in the view, invisible works, or the name cannot be written on upload.
Why does my binary field show a file size instead of a name?+
Without a filename attribute the widget displays the field's raw value, and for saved records Odoo serves a size placeholder such as 108.55 Kb rather than the binary content. Wire the filename attribute and the real name appears.
How do I restrict which file types can be uploaded?+
Two client side layers: accepted_file_extensions pre-filters the picker, and allowed_mime_type, available since Odoo 19, rejects non-matching files with a notification. Neither binds the API, so add a server side constraint when the restriction is mandatory.
Can I add a file upload field without a developer?+
Yes. Odoo Studio's File field creates the binary field with correct filename wiring in one drag. Extension and MIME restrictions still need the options set in XML afterward.
Where does the file actually get stored?+
In the record's binary column, transported as base64. Whether the bytes live in the database or the filestore is decided by Odoo's attachment configuration server side; the widget behaves identically either way, downloading through /web/content.
How is binary different from the image widget?+
Same field type, different rendering contract. This widget shows a name with download and clear controls and never previews. The image widget renders the picture and generates resized variants, and requires configuration when used on relations. Use image when the content is visual, binary when it is a document.
Does the binary widget work in list views?+
Yes, through a dedicated compact variant registered as list.binary, which Odoo selects automatically in list cells. Same options apply.
What changes for binary fields in Odoo 20?+
The development branch adds one option, use_replace_button, which replaces the size text fallback with a clean replace button when no file name is available. Nothing else functional changes in the diff, and we re-verify once Odoo 20 ships in late September 2026.

Documents scattered across your Odoo?

Contracts on subscriptions, EDI receipts on invoices, certificates that auditors ask for by name: file handling is where clean data models earn their keep. We design document flows on Odoo, from filename wiring and server side validation to filestore strategy and portal delivery.

Book a free consultation

How this page was produced

This page was verified by reading binary_field.js in the Odoo 19.0 web module, including extractProps, the filename getter and the download data logic, plus the FileUploader in file_handler.js for how both options are enforced client side. The file was diffed against 18.0, which dates allowed_mime_type to 19.0, and against the public development branch for the Odoo 20 notes. Found a behavior we got wrong? Report it and we will fix the page.