Files API

This API uses the Files mechanism provided by Jmix and exposes it through the REST API to let client applications upload and download files to/from a Jmix application.

Uploading Files

The Upload Files API endpoint /files used with a POST HTTP method allows you to transfer a file to the Jmix application.

There are two different ways of transferring the data:

  1. Using multipart/form-data

  2. Using different content types with the body containing the binary data

Depending on the use case either of those two options might be a better fit. In both situations, the API returns 201 - Created to indicate that the file was successfully stored.

To upload a file, the user must have a role with the rest.fileUpload.enabled specific policy.

Using Multipart/form-data

When using a standard browser form to submit the file to the Jmix application, the preferred way is to use the first option, as browsers by default use the Content-Type multipart/form-data in this case. The form data that contains the file binary needs to be named file so that Jmix takes this part as the file content.

In this example you can see a multipart/form-data request, that uploads the file cat.jpg in its raw HTTP form:

Upload File as Multipart/form-data Request
POST http://localhost:8080/rest/files
Content-Type: multipart/form-data; boundary=WebAppBoundary (1)

--WebAppBoundary
Content-Disposition: form-data; name="file"; filename="cat.jpg" (2)
Content-Type: image/jpeg

< ./cat.jpg (3)
--WebAppBoundary--
1 The Content-Type of the HTTP request is multipart/form-data
2 The Content-Disposition part with the name file expresses the file to upload. The filename there as well.
3 < ./cat.jpg stands for the binary data of the file (the actual binary content is not displayed here).
Response: 201 - Created
{
  "fileRef": "fs://2021/03/12/a3b6011d-9040-151e-7d17-f7ccdf75d72f.jpg?name=cat.jpg", (1)
  "name": "cat.jpg",
  "size": 85862
}
1 The fileRef contains the reference for later use.

In case you want to control the file name under which the file is stored, you can set the URL parameter name like this: POST http://localhost:8080/rest/files?name=dog.jpg. In this case, Jmix will pick up the filename from the parameter and not consider the Content-Disposition.

To limit the uploaded file size use the following application property:

spring.servlet.multipart.max-file-size=10MB

Using Direct Upload

It is also possible to upload a file without using the multipart/form-data content type. Instead, you can use the content type of the file directly. The body of the HTTP request contains the binary file content directly in this case. You need to provide the URL parameter name to indicate which filename to use for the file.

In this example you can see how to use the Direct Request to upload a file:

Upload File as Direct Request
POST http://localhost:8080/rest/files?name=cat-via-direct-request.jpg (1)
Content-Type: image/jpeg (2)

< ./cat.jpg (3)
1 The name URL parameter provides the filename to store.
2 The Content-Type is the actual content type of the file.
3 < ./cat.jpg stands for the binary data of the file (the actual binary content is not displayed here).
Response: 201 - Created
{
  "fileRef": "fs://2021/03/12/2266c97c-cf23-c202-481d-04d972e185b4.jpg?name=cat-via-direct-request.jpg",
  "name": "cat-via-direct-request.jpg",
  "size": 85862
}

Downloading Files

Files that are already uploaded in your Jmix application, can also be downloaded or displayed.

For this you should use the Downloading Files endpoint: /files?fileRef=:fileRef via HTTP GET. The API returns 200 - OK if the file exists together with the file binary content as part of the HTTP body. Otherwise, 404 - Not Found is returned.

In the following example the previously uploaded file is downloaded via the API:

Download File Request
GET http://localhost:8080/rest
            /files
            ?fileRef=fs://2021/03/12/2266c97c-cf23-c202-481d-04d972e185b4.jpg?name=cat-via-direct-request.jpg (1)
1 fs://2021/03/12/2266c97c-cf23-c202-481d-04d972e185b4.jpg?name=cat-via-direct-request.jpg identifies the file by its reference.

The fileRef parameter should always be URL encoded in order to prevent any issues special characters. So the actual URL from above should look like this when requested from the API:

fileRef=fs%3A%2F%2F2021%2F03%2F12%2F2266c97c-cf23-c202-481d-04d972e185b4.jpg%3Fname%3Dcat-via-direct-request.jpg

In case the file exists, the response will contain the file like below:

Response: 200 - OK
Content-Disposition: inline; filename="cat-via-direct-content-type.jpg" (1)
Content-Type: image/jpeg (2)

> ./cat-via-direct-content-type.jpg (3)
1 The Content-Disposition Header contains the filename as well as information on how to handle the file after downloading (inline or attachment).
2 The Content-Type Header contains the content type of the file.
3 > ./cat-via-direct-content-type.jpg stands for the binary data of the file (the actual binary content is not displayed here).

You can manage the Content-Disposition response header by setting the attachment request parameter. If it is set to true, then the response Content-Disposition will be set to "attachment", "inline" value will be used otherwise.

Attachment request parameter
GET http://localhost:8080/rest
            /files
            ?fileRef=<your-file-ref>
            &attachment=true
To download a file, the user must have a role with the rest.fileDownload.enabled specific policy.

Referencing Files from Entities

You can link files to entities after the file has been stored in the Jmix application.

First, you need to upload the file as described in Uploading Files. In the response of the upload, a file reference like fs://2021/03/12/2266c97c-cf23-c202-481d-04d972e185b4.jpg?name=cat-via-direct-request.jpg is returned. You can use this reference when creating / updating entities and link them to the file.

In the following example, the Product entity uses a file reference to store a product image.

Product.java
@JmixEntity
@Table(name = "RSTEX11_PRODUCT")
@Entity(name = "rstex11_Product")
public class Product {

    @PropertyDatatype("fileRef")
    @Column(name = "IMAGE")
    private FileRef image;

    //...
}

When creating a Product via the Create Entities API, you need to pass in the previously received file reference as the value of the image attribute:

Create Product with File Reference Request
POST http://localhost:8080/rest
            /entities
            /rstex11_Product
            ?responseFetchPlan=_local

{
  "name": "Product with Image",
  "price":100,
  "image": "fs://2021/03/13/f623e8ab-524e-51ed-1a9f-b1c1369239e3.jpg?name=cat.jpg"
}
Response: 201 - Created
{
  "id": "ea6f1b3c-0e74-c90b-b009-9f58ac964034",
  "image": "fs://2021/03/13/f623e8ab-524e-51ed-1a9f-b1c1369239e3.jpg?name=cat.jpg",
  "price": 100.00,
  "name": "Product with Image"
}