diff --git a/content/6.files/1.quickstart.md b/content/6.files/1.quickstart.md index d7f588af..8bf0ad1e 100644 --- a/content/6.files/1.quickstart.md +++ b/content/6.files/1.quickstart.md @@ -17,7 +17,7 @@ Use `https://directus.io/docs/img/examples/files-import.png` and the file will b ## Access a File -The file is immediately available via the Data Studio for users with the correct access control. From here, you can download, edit, or replace files. +The uploaded file is immediately available via the Data Studio for users with the correct access control. From here, you can download, edit, or replace files. diff --git a/content/6.files/2.upload.md b/content/6.files/2.upload.md index ff408e69..fb0b81c3 100644 --- a/content/6.files/2.upload.md +++ b/content/6.files/2.upload.md @@ -1,5 +1,58 @@ --- -description: +description: Learn to upload files to Directus via both the data studio or API. --- # Upload Files + +Multiple files can be uploaded simultaneously via both the data studio and via the API. File uploads are not limited to just images, they can be any kind of file. + +## Data Studio + + + +By opening the files module on the left, you will see your file library, which acts as one big folder to store all uploaded files and sub-folders. + +Create a folder called `Images` and click on :icon{name="material-symbols:add-circle-outline-rounded"}. + +You'll see a popup with options for uploading your file: + +- Dragging a file from your desktop. +- Clicking on the popup area to select a file from your machine. +- Clicking on the menu in the popup and selecting "**Import from URL**" + +Optionally, you can also click the file display to open the file details page and fill in information as desired. + +## API + +::snippets +#rest + +```http [POST /files] + +Body must be formatted as a `multipart/form-data` with a final property called `file`. +``` + +#graphql + +Not supported by GraphQL + +#sdk + +```js +import { createDirectus, rest, uploadFiles } from '@directus/sdk'; + +const directus = createDirectus('https://directus.example.com').with(rest()); + +const formData = new FormData(); +formData.append('file_1_property', 'Value'); +formData.append('file', raw_file); +formData.append('file_2_property', 'Value'); +formData.append('file', raw_file_2); + +const result = await directus.request(uploadFiles(formData)); +``` + +:: + +The file contents has to be provided in a property called `file`. All other properties of +the file object can be provided as well, except `filename_disk` and `filename_download`. diff --git a/content/6.files/3.manage.md b/content/6.files/3.manage.md index 50e0745f..81b33213 100644 --- a/content/6.files/3.manage.md +++ b/content/6.files/3.manage.md @@ -1,5 +1,88 @@ --- -description: +description: Learn to view, modify, edit and set files' focal points. --- # Manage Files + +When a file is clicked in the file listing page, the file details page is shown. This is a custom form for viewing assets +and embeds, with core fields included out-of-the-box (see below), and the ability for administrators to add additional +custom fields. This page has the same features and functionality as the +item page. + + + + + +## Action Buttons + +Notice the following buttons in the header: + +- :icon{name="material-symbols:check-circle"} – Saves any edits made to the file. +- :icon{name="material-symbols:tune"} – Please see [Edit an Image](#edit-an-image) to learn more. +- :icon{name="material-symbols:download"} – Downloads the file to your current device. +- :icon{name="material-symbols:drive-file-move-outline"} – Moves selected file(s) to another folder. +- :icon{name="material-symbols:delete-outline"} – Permanently removes the file and its metadata. This action is permanent and cannot be undone. + +::callout{type="info" title="Deleting Files Linked to Items"} + +By default, Directus will not allow you to delete a file until you remove it from any and all related items. However, +this behavior can be reconfigured so that files automatically update when the image is deleted by setting the relational +constraint of your file field to `SET NULL` or `CASCADE` when the file is deleted. + +:: + +## File Details + +The files collection comes pre-configured with the following fields out of the box. New fields can be created and +customized as needed in **Settings > Data Model** under the `directus_files` collection. However the pre-configured Fields cannot be changed or deleted. + + + +- **Preview**: a preview of the image or file. +- **Title**: a title for the File. +- **Description**: a description of the File. +- **Tags**: keywords used for search-ability. +- **Location**: an optional location _(e.g. where a photo was taken)_. +- **Storage**: which storage adapter is used to store the file asset. +- **Filename (Disk)**: This is the actual name of the file in storage. This cannot be modified. +- **Filename (Download)**: allows you to set the name of the file when it is downloaded. + +## File Sidebar + +The file sidebar also includes the following details, which are not editable and serve as metadata. + + + +- **Type**: the MIME type of the file, displayed in the App as a formatted media type. +- **Dimensions**: _images only_. The width and height of the image in pixels. +- **Size**: the file-size the asset takes up in the storage adapter. +- **Created**: the timestamp of when the file was uploaded to the Project. +- **Owner**: the User that uploaded the file to the Project. +- **Modified**: the timestamp of when the file was last modified. +- **Edited By**: the User that modified the File. +- **Folder**: the current parent folder that contains the File. +- **Metadata**: metadata JSON dump of the File's Exif, IPTC, and ICC information. + +## Edit an Image + +Rotate, crop, flip, adjust aspect ratios, or set focal points of an image. + +1. From the **File Library**, click a file to open its detail page. +2. Click the tune button in the top right to open the image editor. +3. Make your changes and click check in the top right to save the updates. + +::callout{type="warning" title="Irreversible Change"} + +Edits overwrite the original file on disk. This can't be reversed. + +:: + +## Set a Focal Point + +By default, Directus will crop images around the center when specific sizes are requested. Focal points change the +center point to specific coordinates. + +1. From the **File Library**, click a file to open its detail page. +2. Click the tune button in the top right to open the image editor. +3. Click the location_searching button to select a focal point. +4. Make your changes and click check in the top right to save the updates. diff --git a/content/6.files/4.access.md b/content/6.files/4.access.md index 4dc3808c..38f1b41c 100644 --- a/content/6.files/4.access.md +++ b/content/6.files/4.access.md @@ -1,5 +1,54 @@ --- -description: +description: Learn how to access uploaded files, authenticate, provide optional filenames and directly download them. --- # Access Files + +Folders and file information are stored in regular collections, which means [user and role access permissions](/auth/access-control) are fully configurable and granular on both folders and files. + +The location of your actual file originals is based on the project's configuration, but you can consistently access them +via the API using the following URL: + +``` +example.com/assets/ +example.com/assets/1ac73658-8b62-4dea-b6da-529fbc9d01a4 +``` + +## Authentication + +Directus leverages stored cookies to authenticate when accessing files, when present. + +If no cookie is stored, you can use the `access_token` query parameter to authenticate, provided the token belongs to a user with the required access to read the file. + +## SEO + +You can provide an optional filename after the UUID to optimize for SEO, for example: + +``` +example.com/assets// +example.com/assets/1ac73658-8b62-4dea-b6da-529fbc9d01a4/directus-logo.png +``` + +This optional filename is also used in the `Content-Disposition` header when the `?download` query parameter is used. + +::callout{type="warning" title="Direct File Access"} + +While you may _technically_ be able to expose your storage adapters root file system and access your raw files through +there, it is recommended that you always use the Directus API. This is the only way that you can take advantage of file +permissions and other built-in features. + +:: + + + +## Downloading a File + +To download an asset with the correct filename, you need to add the `?download` query parameter to the request and the +`download` attribute to your anchor tag. This will ensure the appropriate +[Content-Disposition](https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html) headers are added. Without this, the +download will work on the _same_ domain, however it will have the file's "id" as the filename for cross-origin requests. + +Fetching transformed assets is done by adding a `key` query parameter to the original file's URL. In the Data Studio, you can +configure different asset presets that control the output of any given image. If a requested transformed asset doesn't yet +exist, it is dynamically generated and immediately returned. diff --git a/content/6.files/5.transform.md b/content/6.files/5.transform.md index 5ad032ef..0bb26220 100644 --- a/content/6.files/5.transform.md +++ b/content/6.files/5.transform.md @@ -1,5 +1,170 @@ --- -description: +description: Learn how to transform files and set custom presets for these transformations. --- # Transform Files + +Directus allows you to transform assets using URL query parameters. You can pass these as either query parameters to the `assets` endpoint. If a processed asset does not yet exist, it is dynamically generated, stored, and returned. + +## Custom Transformations + +| Parameter | Description | +| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `width` | How wide the image is in pixels. | +| `height` | How high the image is in pixels. | +| `quality` | The overall image quality (1 to 100), defaults to 100 if omitted. The higher the value, the larger the image size. The lower the value, the more compression artifacts are in the image. | +| `withoutEnlargement` | Disable automatically upscaling the image (true) | +| `format` | What file format to return the image in. One of auto, jpg, png, webp, tiff auto default if omitted, Will try to format it in webp or avif if the browser supports it, otherwise it will fallback to jpg. | +| `fit` | How the image should fit into the provided dimensions, values including:
  • **`cover` (default if omitted)**: try to fit the image into the dimensions while preserving the aspect ratio
  • **`contain`**: contain within the dimensions while using "letterboxing" to fill the rest
  • **`inside`**: Resize to be as large as possible within the dimensions
  • **`outside`**: sesize to be as small as possible within or beyond the dimensions
| + +::callout{type="info" title="Focal Points"} + +When transforming an image with `width` and/or `height` parameters, the focal point is taken from the `focal_point_x` and `focal_point_y` coordinate values stored in the file object, cropping the image around these. This defaults to the image's centre. + +:: + +::snippets +#rest + +```http [GET /assets/c984b755-e201-497e-b0a7-24156ad9c7e0?width=300&height=300&quality=50&fit=contain] + +``` + +#graphql + +Not supported by GraphQL + +#sdk + +```js +import { createDirectus, rest, readAssetRaw } from '@directus/sdk'; + +const FILE_ID = 'c984b755-e201-497e-b0a7-24156ad9c7e0'; + +const directus = createDirectus('directus_project_url').with(rest()); + +const result = await directus.request( + readAssetRaw(FILE_ID, { + width: 300, + height: 300, + quality: 50, + fit: 'contain', + }), +); +``` + +:: + +## Advanced Transformations + +Directus allows full access to the [Sharp API](https://sharp.pixelplumbing.com/), giving you access to more complex image transformations. + +This is done using the `transforms` parameter, whose value consists of a two dimensional array. Each sub-array contains the name of the operation, followed by its arguments: `[["operation1", …arguments], ["operation2", …otherArguments]]`. + +::callout{type="info" title="REST Values"} + +When calling the REST API, datatypes like booleans need to be passed as strings. + +:: + +| sharp API Call | transforms Equivalent | +| ---------------------------------------- | -------------------------------------------------------------- | +| `.rotate(90)` | `[["rotate", 90]]` | +| `.rotate(90).blur(10).tint(255, 0, 255)` | `[["rotate", 90], ["blur", 10], ["tint", "rgb(255, 0, 255)"]]` | +| `negate({lower: 10, upper: 50})` | `[["negate", {"lower": 10, "upper": 50}]]` | + +::snippets +#rest + +```http [GET /assets/c984b755-e201-497e-b0a7-24156ad9c7e0?transforms=[["rotate", 90],["blur", 10],["tint", "rgb(255, 0, 255)"], ["negate", {"lower": 10, "upper": 50}]]] + +``` + +#graphql + +Not supported by GraphQL + +#sdk + +```js +import { createDirectus, rest, readAssetRaw } from '@directus/sdk'; + +const FILE_ID = 'c984b755-e201-497e-b0a7-24156ad9c7e0'; + +const directus = createDirectus('directus_project_url').with(rest()); + +const result = await directus.request( + readAssetRaw(FILE_ID, { + transforms: [ + ['rotate', 90], + ['blur', 10], + ['tint', 'rgb(255, 0, 255)'], + [ + 'negate', + { + lower: 10, + upper: 50, + }, + ], + ], + }), +); +``` + +:: + +Custom and advanced transformations can also be used in conjunction. + +::snippets +#rest + +```http [GET /assets/c984b755-e201-497e-b0a7-24156ad9c7e0?transforms=[["flip"]]&fit=cover&width=300&height=100] + +``` + +#graphql + +Not supported by GraphQL + +#sdk + +```js +import { createDirectus, rest, readAssetRaw } from '@directus/sdk'; + +const FILE_ID = 'c984b755-e201-497e-b0a7-24156ad9c7e0'; + +const directus = createDirectus('directus_project_url').with(rest()); + +const result = await directus.request( + readAssetRaw(FILE_ID, { + transforms: [['flip']], + fit: 'cover', + width: 300, + height: 100, + }), +); +``` + +:: + +## Preset Transformations + +In order to mitigate the creation a large number of files, you can restrict the transformations to a set of presets. You can create your own storage asset preset in the "Settings" section of your project's settings. + +The following options are available: + +- **Allowed Transformations**: for enabling, disabling, or limiting image transformations. +- **Default Folder**: sets the default folder where new assets are added. This does not affect existing files. Be aware + that fields may override this value. +- **Transformation Presets**: sets a specific image transformation configuration to simplify requests or limit usage. + - **Key**: sets unique identifier allowing faster and easier image transformation requests. + - **Fit**: contain _(keeps aspect ratio)_, Cover _(exact size)_, Fit Inside, or Fit Outside. + - **Width**: sets the width of the image. + - **Height**: sets the height of the image. + - **Quality**: adjusts the compression or quality of the image. + - **Upscaling**: when enabled, images won't be upscaled. + - **Format**: changes the output format. + - **Additional Transformations**: adds additional transformations using + [Sharp](https://sharp.pixelplumbing.com/api-constructor). + +You can then use this `key` as a parameter to when requesting a file to apply the preset.