> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Files in data modeling

> Learn how to use files with the core data model and integrate them with assets in Cognite Data Fusion.

Cognite's [core data model](/cdf/dm/dm_reference/dm_core_data_model) uses [*CogniteFile*](/cdf/dm/dm_reference/dm_core_data_model#file) to represent files. The actual file *content* is handled by the [File content](/api-reference/concepts/20230101/file-content) API. This article describes how to use files with the core data model.

## CogniteFile in the core data model

[CogniteFile](/cdf/dm/dm_reference/dm_core_data_model#file) uses the `assets` property to associate a file with one or more [CogniteAssets](/cdf/dm/dm_reference/dm_core_data_model#asset), and other properties to hold metadata of the file.

The **access control** for CogniteFile is handled by the **datamodelinstances** access-control list (ACL). This is the only ACL required to access files in the core data model.

## Working with files using the Python SDK

### Create, retrieve and delete files

To create, retrieve, and delete files using the Python SDK:

<Steps>
  <Step title="Create a file node">
    To **create** a file, use the Cognite Python SDK `CogniteFileApply` data class:

    ```python wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
        from pathlib import Path
        
        from cognite.client.data_classes.data_modeling import NodeId
        from cognite.client.data_classes.data_modeling.cdm.v1 import CogniteFileApply, CogniteFile
        
        # Create a file node in the specified space:
        client.data_modeling.instances.apply(
            CogniteFileApply(name="FileName", space="Space", external_id="File001")
        )
    ```
  </Step>

  <Step title="Retrieve the file node">
    ```python wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
        # Retrieve the created file node:
        file_info_retrieved = client.data_modeling.instances.retrieve_nodes(
            nodes=NodeId("Space", "File001"), node_cls=CogniteFile
        )
        print(file_info_retrieved)
    ```
  </Step>

  <Step title="Upload and download file content">
    ```python wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
        # When you have created the file node, to upload the content:
        client.files.upload_content("file.txt", instance_id=NodeId("Space", "File001"))

        # To download the content:
        client.files.download_to_path("downloaded_file.txt", instance_id=NodeId("Space", "File001"))
    ```
  </Step>

  <Step title="Delete the file">
    ```python wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
        # To delete a file, delete the node:
        client.data_modeling.instances.delete(nodes=NodeId("Space", "File001"))
    ```
  </Step>
</Steps>

### Associate files to CogniteAsset

To associate files to CogniteAsset:

<Steps>
  <Step title="Create or modify file with asset references">
    Provide the instance identifiers of the asset nodes:

    ```python wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
        from cognite.client.data_classes.data_modeling import DirectRelationReference, NodeId
        from cognite.client.data_classes.data_modeling.cdm.v1 import CogniteFileApply, CogniteFile

        # Create or modify a file node with the asset references:
        client.data_modeling.instances.apply(
            CogniteFileApply(
                space="Space",
                name = "FileName",
                external_id="File001",
                assets=[
                    DirectRelationReference("Space", "Asset001"),
                    DirectRelationReference("Space", "Asset002"),
                ],
            )
        )
    ```
  </Step>

  <Step title="Retrieve and verify asset references">
    ```python wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
        # Retrieve the file node to see the asset references:
        file_info_retrieved = client.data_modeling.instances.retrieve_nodes(
            nodes=NodeId("Space", "File001"), node_cls=CogniteFile
        )
        print(file_info_retrieved)
    ```
  </Step>
</Steps>

## Create and upload files using the API

You can ingest files represented with CogniteFile directly through the API. Create a file node in the Data Modeling Service, request an upload link, and upload the file contents. You'll need to replace the placeholders in brackets `{}` used for the endpoint URLs and payload examples with appropriate values for your data model and files.

To create and upload files using the API:

<Steps>
  <Step title="Create an instance in the Data Modeling Service (DMS)">
    **API documentation**: [Create or update nodes/edges](/api-reference/concepts/20230101/instances)

    **Endpoint URL**: `https://{cdf_cluster}.cognitedata.com/api/v1/projects/{cdf_project_name}/models/instances`

    **Payload example**:

    ```json wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    {
        "items": [
            {
                "instanceType": "node",
                "space": "{instance_space}",
                "externalId": "{external_id}",
                "sources": [
                    {
                        "source": {
                            "type": "view",
                            "space": "cdf_cdm",
                            "externalId": "CogniteFile",
                            "version": "v1"
                        },
                        "properties": {
                            "name": "{file_name}",
                            "mimeType": "{mime_type}"
                        }
                    }
                ]
            }
        ]
    }
    ```

    It's important that you include a `source` object mapping to the `CogniteFile` view in the list of `sources` in the payload. Without this, you'll receive an error when requesting an upload link in the next step, because the instance won't be able to be identified by the [File](/api-reference/concepts/20230101/files) service. If you've created a [custom view extending CogniteFile](/cdf/dm/dm_guides/dm_extending_core_data_model) that you want to target instead, however, replace the values for `space`, `externalId` and `version` in the `source` object with the corresponding values for your custom view:

    ```json wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    {
        "source": {
            "type": "view",
            "space": "{custom_space}",
            "externalId": "{CustomFileView}",
            "version": "{view_version}"
        }
    }
    ```

    <Tip>
      You aren't required to provide the `mimeType` property in the `properties` object, but it's useful for visibility in [Search](/cdf/explore/search) and for endpoints like [Engineering diagram detection](/api-reference/concepts/20230101/engineering-diagrams) to be able to process the file.
    </Tip>
  </Step>

  <Step title="Request an upload file link">
    **API documentation**: [POST /files/uploadlink](/api-reference/concepts/20230101/file-content)

    **Endpoint URL**: `https://{cdf_cluster}.cognitedata.com/api/v1/projects/{cdf_project_name}/files/uploadlink`

    **Payload example**:

    ```json wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    {
        "items": [
            {
                "instanceId": {
                    "space": "{instance_space}",
                    "externalId": "{external_id}"
                }
            }
        ]
    }
    ```

    <Info>
      If you are uploading a file larger than 5 GiB you'll need to request a [POST /files/initmultipartupload](/api-reference/concepts/20230101/file-content) instead.
    </Info>
  </Step>

  <Step title="Upload the file contents">
    Send a HTTP PUT request to the `uploadUrl` (or `uploadUrls` if you're using a multipart file upload link) in the response result from the previous query, with the relevant 'Content-Type' and 'Content-Length' headers according to the content of the file.

    Learn more:

    * [POST /files/uploadlink](/api-reference/concepts/20230101/file-content)
    * [POST /files/initmultipartupload](/api-reference/concepts/20230101/file-content)
  </Step>
</Steps>

## Related API reference

<CardGroup cols={2}>
  <Card title="File content" icon="file-arrow-up" href="/api-reference/concepts/20230101/file-content">
    Upload and download file content using instanceId.
  </Card>

  <Card title="Instances API" icon="database" href="/api-reference/concepts/20230101/instances">
    Create and manage file metadata in your data model.
  </Card>
</CardGroup>
