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

# Files

> Upload and manage files with Modelence Cloud storage

Modelence provides built-in file storage through Modelence Cloud. Files are organized by visibility — either `public` (accessible via a permanent URL) or `private` (accessible only via a time-limited signed URL).

Each file operation is available in two forms:

* **Client (`modelence/client`)** — call directly from the browser via built-in methods
* **Server (`modelence/server`)** — call from your server-side code (e.g. inside a mutation or cron job)

## Uploading a File

<Tabs>
  <Tab title="Client">
    `uploadFile` takes a `File` or `Blob`, requests a presigned upload URL from the backend, then POSTs the file directly to storage using a signed form:

    ```ts theme={null}
    import { uploadFile } from 'modelence/client';

    const file = event.target.files[0]; // File from an <input type="file">
    const { filePath } = await uploadFile(file, {
      filePath: 'photo.png',
      contentType: 'image/png',
      visibility: 'public',
    });

    console.log(filePath); // e.g. 'public/photo.png'
    ```
  </Tab>

  <Tab title="Server">
    `getUploadUrl` returns a presigned URL and form fields. POST these together as `FormData` to upload the file directly to storage:

    ```ts theme={null}
    import { getUploadUrl } from 'modelence/server';
    import fs from 'fs/promises';

    const { url, fields, filePath } = await getUploadUrl({
      filePath: 'photo.png',
      contentType: 'image/png',
      visibility: 'public',
    });

    const data = await fs.readFile('./photo.png');
    const formData = new FormData();
    for (const [key, value] of Object.entries(fields)) {
      formData.append(key, value);
    }
    formData.append('file', new Blob([data], { type: 'image/png' }));

    await fetch(url, { method: 'POST', body: formData });

    console.log(filePath); // e.g. 'public/photo.png'
    ```
  </Tab>
</Tabs>

The `visibility` field controls access:

* `"public"` — the file is accessible via a permanent URL
* `"private"` — the file requires a signed URL to access

## Getting a File URL

Returns a URL for displaying or linking to a file. For public files this is a permanent URL; for private files it is a time-limited presigned URL.

<Tabs>
  <Tab title="Client">
    ```ts theme={null}
    import { getFileUrl } from 'modelence/client';

    const { url } = await getFileUrl('public/photo.png');
    console.log(url); // Permanent public URL

    const { url: privateUrl } = await getFileUrl('private/report.pdf');
    console.log(privateUrl); // Time-limited presigned URL
    ```
  </Tab>

  <Tab title="Server">
    ```ts theme={null}
    import { getFileUrl } from 'modelence/server';

    const { url } = await getFileUrl('public/photo.png');
    console.log(url); // Permanent public URL

    const { url: privateUrl } = await getFileUrl('private/report.pdf');
    console.log(privateUrl); // Time-limited presigned URL
    ```
  </Tab>
</Tabs>

## Downloading a File

Returns a presigned download URL for a private file.

<Tabs>
  <Tab title="Client">
    ```ts theme={null}
    import { downloadFile } from 'modelence/client';

    const { downloadUrl } = await downloadFile('private/report.pdf');
    // Redirect the user to downloadUrl or fetch it client-side
    ```
  </Tab>

  <Tab title="Server">
    ```ts theme={null}
    import { downloadFile } from 'modelence/server';

    const { downloadUrl } = await downloadFile('private/report.pdf');
    // Redirect the user to downloadUrl or fetch it server-side
    ```
  </Tab>
</Tabs>

## Deleting a File

<Tabs>
  <Tab title="Client">
    ```ts theme={null}
    import { deleteFile } from 'modelence/client';

    await deleteFile('public/photo.png');
    await deleteFile('private/report.pdf');
    ```
  </Tab>

  <Tab title="Server">
    ```ts theme={null}
    import { deleteFile } from 'modelence/server';

    await deleteFile('public/photo.png');
    await deleteFile('private/report.pdf');
    ```
  </Tab>
</Tabs>

## File Paths

File paths always include the visibility prefix: `public/<path>` or `private/<path>`. The upload functions return the full `filePath` (including prefix) in their result, which you can store and pass to the other functions.

```ts theme={null}
import { uploadFile } from 'modelence/client';

const { filePath } = await uploadFile(file, {
  filePath: 'avatars/user-123.png',
  contentType: 'image/png',
  visibility: 'private',
});
// filePath === 'private/avatars/user-123.png'

const { url } = await getFileUrl(filePath);
```
