What this is about
You read the record of a file model like any object. You fetch the content with an endpoint of its own:
GET /api/rest/fileasset/f1…/file?access_token=eyJhbGciOi…200
Content-Type: application/pdf
Content-Disposition: inline; filename=Contract.pdf
Cache-Control: no-store
…bytes of the file…What is special: the token is in the URL, in the parameter access_token, not in the Authorization header.
Why the token is in the URL
A link <a href>, an image <img src> or a PDF viewer in the browser fetch an address by themselves. They cannot send an Authorization header. So that such links work, the download endpoint takes the token as a parameter, and only that way: without access_token the request is rejected, even if a header is present.
sequenceDiagram
participant U as User
participant B as Browser
participant D as CDMS
participant F as File storage
U->>B: clicks on "Contract.pdf"
B->>D: GET /fileasset/f1…/file?access_token=…
D->>D: check token (tenant served?)
D->>D: read record: read role, visibility
D->>D: check download role
D->>F: read content
F-->>D: bytes
D-->>B: 200, Content-Type from mimeType
B-->>U: shows the file or saves it
The checks
-
CIASTokenIs the token from
access_tokenvalid, is its tenant served, and does it name a tenant at all inMULTI?↳ no 403 with the key from CIAS, without a tenant inMULTIcias.authentication.tenant-requiredas in the filter chain; an unreadable token counts as anonymous and fails at the next station -
CDMSRead recordRead role of the model and visibility of the row, as with
POST /read/{id}↳ no 403 without read role, 404 if invisible or not present -
CDMSDownload roleDo you have the download role of the model?↳ no rejected
-
File storageContentIs the content under the
fileId, and is it readable?↳ nofile-not-foundorfile-not-readable - 200 with the bytes
The response
| Header | Value | Effect |
|---|---|---|
Content-Type | mimeType of the record | the browser knows how to display the file |
Content-Disposition | inline; filename=<name> | the browser shows the file if it can, and suggests the name when saving |
Cache-Control | no-store | browsers and proxies do not keep the file in their cache |
If the browser should always save the file instead of showing it, set the HTML attribute download on the link: <a href="…/file?access_token=…" download>.
Variants
When: GET {basis}/{id}/file?access_token=…
As above: all checks, response with Content-Type, Content-Disposition and Cache-Control.
When: GET {basis}/file?access_token=…, without id
The server finds the one object itself. If there is none yet, you get 404 file-not-found. Only the download role is checked, no read role is needed here. The response contains only the bytes as application/octet-stream, without file name and without file type.
Result: See Singletons.
When: The file hangs on another object, such as Company.logo.
Read the parent with the id of the child, for example "response": ["+", {"field": "logo", "response": ["id", "name"]}], and then fetch the file through the endpoint of the file model: GET /company/logo/{logoId}/file.
The endpoint exists as soon as the file model has the endpoint DOWNLOAD or READ. See Which endpoints a model has.
Pitfalls
What comes next
- Swapping the file: Replacing and renaming
- Older states: File versions
- The token: The path of the token