> For the complete documentation index, see [llms.txt](https://docs.ninox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ninox.com/ninox-scripting/automate-your-workflows/work-with-functions/files-and-export.md).

# Files and export

Learn how to import files, create exports, inspect attachments, and manage file and view sharing in Ninox scripts.

Files help you move data into and out of Ninox. You can import attachments, create text or spreadsheet exports, bundle files, generate links, and control who can access shared files and views. This chapter shows you the core file functions for common automation and reporting tasks.

<table data-search="false"><thead><tr><th width="214.921875">Function (A-Z)</th><th>Task</th></tr></thead><tbody><tr><td><code>appendTempFile()</code></td><td>Add content to a temporary file</td></tr><tr><td><code>createTempFile()</code></td><td>Create a temporary file for staged output</td></tr><tr><td><code>createTextFile()</code></td><td>Create a plain text file</td></tr><tr><td><code>createXLSX()</code></td><td>Export data to an XLSX file</td></tr><tr><td><code>createZipFile()</code></td><td>Bundle several files into a ZIP archive</td></tr><tr><td><code>file()</code></td><td>Return a single file reference</td></tr><tr><td><code>fileMetadata()</code></td><td>Return file details such as name, size, and date</td></tr><tr><td><code>files()</code></td><td>Return multiple file references</td></tr><tr><td><code>fileUrl()</code></td><td>Return a download link for a file</td></tr><tr><td><code>importFile()</code></td><td>Import a file into Ninox</td></tr><tr><td><code>loadFileAsBase64()</code></td><td>Return file content as a Base64 string</td></tr><tr><td><code>loadFileAsBase64URL()</code></td><td>Return file content as a Base64 data URL</td></tr><tr><td><code>printAndSaveRecord()</code></td><td>Print a PDF from a record and return its download link</td></tr><tr><td><code>removeFile()</code></td><td>Delete a file</td></tr><tr><td><code>renameFile()</code></td><td>Rename a file</td></tr><tr><td><code>urlOf()</code></td><td>Return a URL for a record</td></tr></tbody></table>

## Import, create, and process files

Use these functions when you want to bring a file into Ninox, generate output, or work with one or more file objects in a script.

### Import a file with `importFile()`

Use `importFile()` to bring a file into Ninox where file import is supported.

Use it when you want to:

* Add external content to a workflow.
* Move a source file into Ninox before further processing.
* Attach a file from a URL to a record.
* Save generated file output into a file field.

`importFile(nid, string)`\
`importFile(nid, link)`\
`importFile(nid, string, string)`\
`importFile(nid, link, string)`

* `nid` target record
* `string` or `link` (second argument of the record form): source URL or file link
* `string` (optional third argument of the record form): filename to save

`importFile()` returns a file object.

#### Let’s take a look at an example:

```ninox
importFile(this, "https://ninox.com/example.jpg", "Image.jpg")
```

Imports the file from the URL and attaches it to the current record as "Image.jpg".

{% hint style="warning" %}
Use valid characters when generating file names. Slashes `/` are not allowed.\
For example, do not use an unformatted `today()` value if it produces `08/23/2026`.\
Format the date as shown above. Otherwise, PDF generation fails.
{% endhint %}

### Create and save a PDF from a record with `printAndSaveRecord()`

Use `printAndSaveRecord()` to generate a PDF from a record using a print layout. It saves the PDF in Ninox and returns a download link.

Use it when you want to:

* Save a PDF version of a printed document.
* Combine printing with file output in one step.
* Use the returned file link to import the file as an attachment.

`printAndSaveRecord(nid, string)`

* `nid` the record you want to print
* `string` the print layout name

`printAndSaveRecord()` returns a download link to the saved PDF file.

{% hint style="info" %}
`printAndSaveRecord()` runs only on the server. Run it inside a `do as server ... end` block.
{% endhint %}

#### Examples

```ninox
do as server
printAndSaveRecord(this, "Invoice")
end
```

Generates a PDF for the current record and returns a link to the saved file.

Combine `printAndSaveRecord()` with `importFile()` to import the file, attach it to the current record, and display it in the "Invoice" field.

```
do as server
invoice := importFile(this, printAndSaveRecord(this, "Invoice layout"), invoice_number + ".pdf")
end
```

Prints the current record with the "Invoice layout" and saves the PDF in the "Invoice" file field. Its filename combines the "Invoice number" field value with ".pdf".

Tips:

* Use clear layout names so scripts stay readable.
* Pair print layouts with `format()` for clean numbers and dates.
* Pass a filename with `importFile()` when the source URL does not provide a useful name.
* You can use `importFile()` with generated file links, not just external URLs.

### Build files with `createTextFile()`

Use `createTextFile()` when you already have the final content and want a ready file immediately.

`createTextFile(nid, string, string)`\
`createTextFile(nid, string, string, any)`

* `nid` target record
* `string` (second argument) file content
* `string` (third argument) filename
* `any` options such as `{ encoding: "utf8" }`. The following encodings are available:
  * `utf8`
  * `utf16le`
  * `latin1`
  * `base64`
  * `base64url`
  * `hex`
  * `ascii`

#### Let’s take a look at some examples:

```ninox
let myFile := createTextFile(this, "Hello", "notes.txt");
myFile
```

Creates a text file named "notes.txt" with the content "Hello".

```ninox
let myFile := createTextFile(this, text(rich_text), "MyTextFileExample.txt");
myFile
```

Creates a plain text file from the visible text content of the rich text field.

```ninox
let myFile := createTextFile(this, raw(rich_text), "MyTextFileExample.html");
myFile
```

Creates an HTML file from the raw rich text content.

<pre class="language-ninox"><code class="lang-ninox">do as server 
    createTextFile(this,raw(rich_text),"MyTextFileExample_UTF8.html",{
        encoding: "utf8"
    })
<strong>end
</strong></code></pre>

Creates the file with explicit UTF-8 encoding.

Tips:

* You can choose any filename and extension, for example, `.txt`, `.csv`, or `.html`.
* If you do not save the returned file elsewhere, for example in a File field, Ninox attaches it to the record.

{% hint style="info" %}
The `encoding` option is available only in server context. Therefore, you need to run `createTextFile()` inside `do as server ... end` if you use the encoding option.
{% endhint %}

`createTempFile()` creates a temporary file on the Ninox server with initial content and returns a link to that file.

### Create files and append content with `createTempFile()` and `appendTempFile()`

`appendTempFile()` adds content to a temporary file on the Ninox server by using the link returned from `createTempFile()`.

Use them when you want to:

* Build large exports in several steps.
* Write logs or report lines one after another.
* Generate a plain text attachment for download or sharing.

`createTempFile(string, string)`

* `string` (1st argument) initial content for the temporary file
* `string` (2nd argument) filename for the temporary file

`createTempFile()` returns a link to the temporary file.

{% hint style="warning" %}
Because this file is temporary, it is automatically deleted after 24 hours.
{% endhint %}

`appendTempFile(link, string)`\
`appendTempFile(string, string)`

* `link` or `string` (1st argument) the temporary file link returned by `createTempFile`
* `string` (2nd argument) the content chunk to append

#### Let’s take a look at some examples:

```ninox
do as server
	let header := "Name,email
	";
	url_field := createTempFile(header, "export.csv");
end
```

This creates a temporary CSV file with a header line. It stores the file link in the "URL field" of the current record.

```ninox
do as server
	let linebreak := "
";
	for myC in select contacts do
		let line := myC.name + "," + myC.email + linebreak;
		appendTempFile(url_field, line)
	end
end
```

This appends one line for each contact to the temporary CSV file. The "URL field" in the current record links to the file.

```ninox
do as server
	let linebreak := "
";
	let header := "Name,email" + linebreak;
	url_field := createTempFile(header, "export.csv");
	for myC in select contacts do
		let line := myC.name + "," + myC.email + linebreak;
		appendTempFile(url_field, line)
	end
end
```

This creates a temporary CSV file, writes the header, and appends a line for each contact in one script.

Tips:

* Use a temporary file when the content is assembled over a short time as temporary files are deleted automatically after some time.
* `createTempFile()` creates the file only when the initial content is not empty.
* The temporary file must still exist when `appendTempFile()` runs.
* `appendTempFile()` is useful for large or long-running exports.

{% hint style="info" %}
Both functions must run on the server. Run them inside a `do as server ... end` block.
{% endhint %}

### Export data with `createXLSX()`

Use `createXLSX()` to dynamically create customizable, styled, multi-sheet Excel files directly from your app.

Use it when you want to:

* Send filtered records to a user.
* Build styled Excel files with custom columns and rows.
* Create multi-sheet exports for reporting or handoff workflows.

The resulting file is saved directly in Ninox, offering dynamic data management and formatting options.

`createXLSX(nid, any, string)`

* `nid` target record, where the file should be saved
* `any` workbook or worksheet definition
* `string` filename for the XLSX export

`createXLSX()` returns a file object.

#### Let’s take a look at some examples:

Due to the complexity of this function, let's split the examples into the following steps:

1. Define the columns and rows.
2. Define the worksheet structure.
3. Use the `createXLSX` function.
4. Define styles and formatting (optional).

#### **Define columns and rows** <a href="#define-columns-and-rows" id="define-columns-and-rows"></a>

First, create an object to define the columns:

```json
let columns := [
    {
        header: "Name",
        key: "name",
        width: 10,
    },
    {
        header: "Age",
        key: "age",
        width: 10
    },
    {
        header: "URL",
        key: "url",
        width: 30
    },
    {
        header: "Description",
        key: "description",
        width: 20
    }
];
```

Next, define the rows. You can use supported special fields (described below) if needed:

```json
let rows := [
{
name: "Luis Gómez",
age: 30,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
}
},
{
name: "Maria Silva",
age: 25,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
}
},
{
name: "Ayesha Khan",
age: 35,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
}
},
{
name: "Li Wei",
age: 40,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
}
},
{
name: "Rajesh Kumar",
age: 21,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
}
},
{
name: "Sofia Müller",
age: 24,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
}
}
];
```

#### Define worksheet structure <a href="#define-worksheet-structure" id="define-worksheet-structure"></a>

Define a worksheet with columns and rows:

```json
let worksheets := {
Sheet1: {
columns: columns,
rows: rows
}
};
```

#### Use `createXLSX` <a href="#use-createxlsx" id="use-createxlsx"></a>

Call the `createXLSX` function with the defined worksheets:

```json
my_file_field := createXLSX(this, worksheets, "example.xlsx")
```

Saves the created file in the <i class="fa-paperclip-vertical">:paperclip-vertical:</i> **Files** tab of the current record and displays it in a field field of your form view.

```json
createXLSX(this, worksheets, "example.xlsx")
```

Saves the file only in the <i class="fa-paperclip-vertical">:paperclip-vertical:</i> **Files** tab of the current record.

#### Define styles and formatting (optional) <a href="#define-styles-and-formatting-optional" id="define-styles-and-formatting-optional"></a>

Apply a style to a header cell:

```json
let columns := [{
    header: "Name",
    key: "name",
    width: 10,
    headerStyle: {
        font: {
            bold: true
        }
    }
}];
```

Apply style to an entire column except the header:

```json
let columns := [{
			header: "Name",
			key: "name",
			width: 10,
			style: {
				font: {
					name: "Comic Sans MS"
				}
			}
		}]
```

Apply style to an entire row:

```json
let rows := [
{
name: "Luis Gómez",
age: 30,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
},
			styles: [{
					fill: {
						type: "pattern",
						pattern: "solid",
						fgColor: {
							argb: "F08080"
						}
					}
				}]]
}
];
```

Apply style to specific cells in a row:

```json
let rows := [
{
name: "Luis Gómez",
age: 30,
url: {
text: "www.google.com",
hyperlink: "http://www.google.com",
tooltip: "www.google.com"
},
styles: [
{
targets: ["name", "age"],
fill: {
type: "pattern",
pattern: "solid",
fgColor: {
argb: "F08080"
}
}
}
]
}
];
```

Finally, when you've saved your script, click the button to create an Excel file.

#### Supported styles and formatting options <a href="#supported-styles-and-formatting-options" id="supported-styles-and-formatting-options"></a>

**Font**

```json
{
  font: {
    name: "Arial Black",
    color: { argb: "FF00FF00" },
    family: 2,
    size: 14,
    italic: true,
    underline: true,
    bold: true
  }
}
```

**Font formatting options**

<table data-search="false"><thead><tr><th width="134.85546875">Font property</th><th>Description</th><th>Example value(s)</th></tr></thead><tbody><tr><td>name</td><td>Specifies the font name.</td><td>"Arial"<br>"Calibri"<br>etc.</td></tr><tr><td>family</td><td>Specifies the font family for fallback as an integer value.</td><td>1 - Serif<br>2 - Sans Serif<br>3 - Mon<br>Others - unknown</td></tr><tr><td>scheme</td><td>Specifies the font scheme.</td><td>"minor"<br>"major"<br>"none"</td></tr><tr><td>charset</td><td>Specifies the font character set as an integer value.</td><td>1<br>2<br>etc.</td></tr><tr><td>size</td><td>Specifies the font size as an integer value.</td><td>9<br>10<br>12<br>16<br>etc.</td></tr><tr><td>color</td><td>Specifies the font color as an ARGB object.</td><td>{ argb: "FFFF0000" }</td></tr><tr><td>bold</td><td>Specifies whether the font is bold, indicating weight.</td><td>true<br>false</td></tr><tr><td>italic</td><td>Specifies whether the font is italic, indicating slope.</td><td>true<br>false</td></tr><tr><td>underline</td><td>Specifies the font underline style.</td><td>true<br>false<br>"none"<br>"single"<br>"double"<br>"singleAccounting"<br>"doubleAccounting"</td></tr><tr><td>strike</td><td>Specifies whether the font has strikethrough.</td><td>true<br>false</td></tr><tr><td>outline</td><td>Specifies whether the font has an outline.</td><td>true<br>false</td></tr><tr><td>vertAlign</td><td>Specifies the font's vertical alignment.</td><td>"superscript"<br>"subscript"</td></tr></tbody></table>

**Alignment**

```json
{ alignment: { vertical: "top", horizontal: "left" }
```

**Alignment formatting options**

<table data-search="false"><thead><tr><th width="162.87890625">horizontal</th><th width="106.08203125">vertical</th><th width="81.1484375">wrapText</th><th width="89.84375">shrinkToFit</th><th width="90.4609375">indent</th><th width="106.26171875">readingOrder</th><th width="105.7734375">text Rotation</th></tr></thead><tbody><tr><td>left</td><td>top</td><td>true</td><td>true</td><td>integer</td><td>rtl</td><td>0 to 90</td></tr><tr><td>center</td><td>middle</td><td>false</td><td>false</td><td></td><td>ltr</td><td>-1 to -90</td></tr><tr><td>right</td><td>bottom</td><td></td><td></td><td></td><td></td><td>vertical</td></tr><tr><td>fill</td><td>distributed</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>justify</td><td>justify</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>centerContinuous</td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>distributed</td><td></td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>

**Border**

```json
// set single thin border
{
  border: {
    top: { style: "thin" },
    left: { style: "thin" },
    bottom: { style: "thin" },
    right: { style: "thin" }
  }
}

// set double thin green border
{
  border: {
    top: { style: "double", color: { argb: "FF00FF00" } },
    left: { style: "double", color: { argb: "FF00FF00" } },
    bottom: { style: "double", color: { argb: "FF00FF00" } },
    right: { style: "double", color: { argb: "FF00FF00" } }
  }
}

// set thick red cross
{
  border: {
    diagonal: { up: true, down: true, style: "thick", color: { argb: "FFFF0000" } }
  }
}
```

**Valid border styles**

{% columns %}
{% column width="25%" %}

* thin
* dotted
* dashDot
* hair
  {% endcolumn %}

{% column width="33.333333333333336%" %}

* dashDotDot
* slantDashDot
* mediumDashed
* mediumDashDotDot
  {% endcolumn %}

{% column width="41.666666666666664%" %}

* mediumDashDot
* medium
* double
* thick
  {% endcolumn %}
  {% endcolumns %}

**Patterned fill**

```json
// fill with red dark vertical stripes
{
  fill: {
    type: "pattern",
    pattern: "darkVertical",
    fgColor: { argb: "FFFF0000" }
  }
}

// fill with yellow dark trellis and blue behind
{
  fill: {
    type: "pattern",
    pattern: "darkTrellis",
    fgColor: { argb: "FFFFFF00" },
    bgColor: { argb: "FF0000FF" }
  }
}

// fill with solid coral
{
  fill: {
    type: "pattern",
    pattern: "solid",
    fgColor: { argb: "F08080" }
  }
}

// fill with blue-white-blue gradient from left to right
{
  fill: {
    type: "gradient",
    gradient: "angle",
    degree: 0,
    stops: [
      { position: 0, color: { argb: "FF0000FF" } },
      { position: 0.5, color: { argb: "FFFFFFFF" } },
      { position: 1, color: { argb: "FF0000FF" } }
    ]
  }
}

// fill with red-green gradient from center
{
  fill: {
    type: "gradient",
    gradient: "path",
    center: { left: 0.5, top: 0.5 },
    stops: [
      { position: 0, color: { argb: "FFFF0000" } },
      { position: 1, color: { argb: "FF00FF00" } }
    ]
  }
}
```

**Pattern fill options**

<table><thead><tr><th width="107.48046875">Property</th><th width="107.1796875">Required</th><th>Description</th></tr></thead><tbody><tr><td>type</td><td>Yes</td><td>Specifies that this fill uses a pattern.</td></tr><tr><td>pattern</td><td>Yes</td><td>Specifies the type of pattern.<br>See <strong>Valid pattern types</strong> below.</td></tr><tr><td>fgColor</td><td>No</td><td>Specifies the pattern's foreground color.<br>The default color is black.</td></tr><tr><td>bgColor</td><td>No</td><td>Specifies the pattern's background color.<br>The default color is white.</td></tr></tbody></table>

{% hint style="info" %}
To fill a cell using the `solid` pattern, you don't need to specify `bgColor`.
{% endhint %}

**Valid pattern types**

{% columns %}
{% column %}

* none
* solid
* darkGray
* mediumGray
* lightGray
* gray125
* gray0625
  {% endcolumn %}

{% column %}

* darkHorizontal
* darkVertical
* darkDown
* darkUp
* darkGrid
* darkTrellis
  {% endcolumn %}

{% column %}

* lightHorizontal
* lightVertical
* lightDown
* lightUp
* lightGrid
* lightTrellis
  {% endcolumn %}
  {% endcolumns %}

**Gradient fill**

<table><thead><tr><th width="114.33203125">Property</th><th width="112.1953125">Required</th><th>Description</th></tr></thead><tbody><tr><td>type</td><td>Yes</td><td>Specifies that this fill uses a gradient.</td></tr><tr><td>gradient</td><td>Yes</td><td>Defines the type of gradient, which can be either "angle" or "path."</td></tr><tr><td>degree</td><td>angle</td><td><ul><li>Indicates the gradient's direction.</li><li>A value of 0 places it from left to right.</li><li>Values from 1 to 359 rotate the direction clockwise.</li></ul></td></tr><tr><td>center</td><td>path</td><td><ul><li>Specifies the relative coordinates for the start of the gradient path.</li><li>"Left" and "Top" values range from 0 to 1.</li></ul></td></tr><tr><td>stops</td><td>Yes</td><td><ul><li>Specifies the gradient's color sequence.</li><li>An array of objects defines the position and color, starting at position 0 and ending at position 1.</li><li>Additional positions can specify other colors on the path.</li></ul></td></tr></tbody></table>

**Supported special fields**

The function supports special fields like hyperlinks, rich text, and formulas:

* Hyperlinks provide links to web content or internal references.
* Rich text allows for mixed-format text, including bold, italic, and other font styles.
* Formulas enable cells to compute values dynamically.
* Dates can be used directly from Ninox.

**Hyperlink**

```json
// link to web
value := {
  text: "www.mylink.com",
  hyperlink: "http://www.mylink.com",
  tooltip: "www.mylink.com"
};
// internal link
value := {
  text: "Sheet2",
  hyperlink: "#'Sheet2'!A1"
};
```

**Rich text** (in XLSX)

```json
value := {
  richText: [
    { text: "This is" },
    { font: {italic: true}, text: "italic" },
  ]
};
```

**Formula** (XLSX)

```json
value := { formula: "A1+A2" };
value := { formula: "SUM(A1,A2)" };
```

**Date** (XLSX)

```json
let columns := [{
    header: "Birthdate",
    key: "birthdate",
    width: 10,
    date: true
}];
```

Tips:

* Filter the selection before export when the file should contain only relevant records.
* Use a clear filename so recipients know what they received.
* Use the workbook form when you need custom columns, styles, or multiple sheets.
* Special cell values can include hyperlinks, rich text, formulas, and dates.
* Save the returned file in a file field to make it visible on the form view in a specific data context.

### Bundle files with `createZipFile()`

Use `createZipFile()` to combine several files into one ZIP archive.

Use it when you want to:

* Deliver several files in one download.
* Package reports and attachments together.
* Reduce manual steps for the recipient.

`createZipFile(nid, [file], string)`

* `nid` target record
* `[file]` files to include
* `string` ZIP filename

`createZipFile()` returns a file object and saves it in the <i class="fa-paperclip-vertical">:paperclip-vertical:</i> **Files** tab of the assigned `nid`.

#### Let’s take a look at some examples:

```ninox
do as server
    let products := (select products).photo;
    createZipFile(this, products, "Products.zip")
end
```

Creates a ZIP archive with all files from the "Photo" field in the selected `Products` records.

```ninox
do as server
    createZipFile(this, files(this), "Product.zip")
end
```

Creates a ZIP archive with all files attached to the current record.

```ninox
do as server
    createZipFile(this, [photo], "Product.zip")
end
```

Creates a ZIP archive from one file in a file field by wrapping it in an array.

Tips:

* `createZipFile()` currently works only in server context, therefore wrap the function always in `do as server ... end`.
* Use `files(this)` when you want to ZIP *all* files attached to the current record.
* Wrap a single file in an array when you want to create a ZIP from one attachment.

{% hint style="info" %}
Creating and sharing files can vary by client capabilities. Test export and sharing scripts in the environments your team uses most.
{% endhint %}

### Return one or more file objects with `file()` and `files()`

Use `file()` when you need one file reference. Use `files()` when you need the full list of files attached to a record.

Use them when you want to:

* Pass file objects to other file functions.
* Pick one specific attachment by filename from a record.

`file(nid, string)`\
`files(nid)`

* `nid` record that contains the file attachment(s)
* `string` exact filename of the attachment you want to return

`files()` returns an array of file objects.

#### Let’s take a look at some examples:

```ninox
files(this)
```

Returns all attachments of the current record as an array.

```ninox
count(files(this))
```

Returns the number of attachments on the current record.

```ninox
file(this, "My wanted document.pdf")
```

Returns the file attachment from the current record with the name "My wanted document.pdf".

Tips:

* Use `files()` when users can attach several files and you want all of them.
* Use `file()` with the record ID and exact name of the file, when a record has several attachments and you need one exact file.
* Match the filename exactly when you use the record-and-name form.

### Check file details with `fileMetadata()`

Use `fileMetadata()` to inspect a file before you share, export, or process it.

Use it when you want to:

* Check file size, name or modification date.
* Read file details from a record when you know the filename.

`fileMetadata(nid, string)`

* `nid` record that contains the file attachment
* `string` exact filename of the attachment you want to inspect

`fileMetadata()` returns JSON with details such as `name`, `size`, and `modifiedDate`.

#### Let’s take a look at some examples:

```ninox
fileMetadata(this, "Invoice_001.pdf")
```

Returns file metadata such as:

```json
{ "name": "Invoice_001.pdf", "size": 95935, "modifiedDate": 1661385600000 }
```

```ninox
let myName := item(split(item(split(text(invoice), ":"), 3), """"), 1);
metadata_field := fileMetadata(this, myName)
```

Returns the metadata for the file whose name is extracted with [text and strings](/ninox-scripting/automate-your-workflows/work-with-functions/text-and-strings.md) functions from the "Invoice" file field.

Tips:

* Check metadata before sending large or sensitive files.
* Use metadata checks in approval or export workflows.
* Use the record-and-name form when a record has several attachments and you need one exact file.
* `modifiedDate` is returned as a timestamp.

## Rename or remove files

Use these functions when you want to manage existing files after creation, import, or export.

### Rename or remove a file with `renameFile()` and `removeFile()`

Use `renameFile()` to change the filename. Use `removeFile()` to delete a file.

Use them when you want to:

* Standardize export names.
* Clean up temporary output.
* Remove outdated or incorrect files.

`renameFile(file, string)`\
`renameFile(nid, string, string)`\
`removeFile(file)`\
`removeFile(nid, string)`

* `file` file object you want to rename or remove
* `string` new filename for `renameFile`
* `nid` record that contains the file you want to rename or remove
* `string` (second argument of `renameFile`) current filename
* `string` (third argument of `renameFile`) new filename
* `string` (second argument of `removeFile`) exact filename you want to remove

#### Let’s take a look at some examples:

```ninox
let myFile := createTextFile( "Hello", "notes.txt");
renameFile(myFile, "readme.txt")
```

Renames the file to "readme.txt".

```ninox
image := renameFile(image, "A1234_Front_0729.jpg")
```

Renames the file in the "Image" field and updates the field with the renamed file.

```ninox
renameFile(this, "Offer_0724.pdf", "Offer_0724-1.pdf")
```

Renames the attached file on the current record.

```ninox
removeFile(Image);
Image := null
```

Removes the file behind the "Image" field and then clears the field reference.

```ninox
removeFile(this, "Offer_0724.pdf")
```

Removes the file "Offer\_0724.pdf" from the current record.

Tips:

* Remove files only when you are sure they are no longer needed.
* On native apps, run `renameFile()` and `removeFile()` in server context.
* Use the form `removeFile(nid, string)` when a record has several attachments and you want to remove one exact file.

## Use record URLs to link to specific data

Use these functions when you want to create a link to a record.

### Return a record URL with `urlOf()`

Use `urlOf()` to return a record URL.

Use it when you want to:

* Share a direct link to the current record.
* Store a record URL in a message or an export.
* Pass a link to another system.

`urlOf(nid)`

* `nid` the record whose URL you want to retrieve

`urlOf()` returns a record URL.

#### Let's take a look at an example:

```ninox
urlOf(this)
```

Returns the URL of the current record.

### Create a link with `fileUrl()`

Use `fileUrl()` to return a URL for a file.

Use it when you want to:

* Show or send a download link.
* Link to one specific attachment on a record.

`fileUrl(nid, string)`

* `nid` the record that contains the file attachment
* `string` the exact filename of the attached file you want to link to

`fileUrl()` returns a link.

#### Let’s take a look at an example:

```ninox
let fileName := item(split(raw(image), """"), 11);
fileUrl(this, fileName)
```

Extracts the filename from the metadata of the "Image" field and returns a link to that specific file.

Tips:

* `fileUrl()` is designed for client-side use.
* You cannot use `fileUrl()` in triggers or inside `do as server`, `do as transaction`, or `do as deferred` blocks.
* The generated link uses information from the currently logged-in user, so it is not available in server-side execution.

## Load files as Base64 for APIs and embedding

Use these functions when you need the actual file content, not just the file object or a link.

### Return file content with `loadFileAsBase64()` and `loadFileAsBase64URL()`

Use `loadFileAsBase64()` to return raw Base64 text. Use `loadFileAsBase64URL()` when you need a ready `data:` URL.

Use them when you want to:

* Send file content to an API.
* Embed a file in generated output.
* Store binary file content as text for a follow-up request.

`loadFileAsBase64(file)`\
`loadFileAsBase64(nid, string)`\
`loadFileAsBase64URL(file)`\
`loadFileAsBase64URL(nid, string)`

* `file` the file object or supported file source to encode
* `nid` the record that contains the file attachment
* `string` the exact filename of the attachment you want to encode

`loadFileAsBase64()` returns the file content as a Base64 string.

`loadFileAsBase64URL()` returns the file content as a Base64 data URL.

#### Let’s take a look at some examples:

```ninox
loadFileAsBase64(this, "myFoto.jpg")
```

Returns the attachment "myFoto.jpg" from the current record as a Base64 string.

```ninox
loadFileAsBase64(photo)
```

Returns the file in the "Photo" field as a Base64 string.

```ninox
loadFileAsBase64URL(this, "myPhoto.jpg")
```

Returns the attachment "myPhoto.jpg" from the current record as a Base64 data URL.

```ninox
let myIm := first((select contacts where score = 100).submitted_photo);
let myWin := loadFileAsBase64URL(myIm);
winners_photo := myWin;
```

Retrieves the record with a "Score" of 100 from the "Contacts" table. Gets the file from the "Submitted Photo" field.\
The file is converted to a Base64 data URL.\
The URL is stored in the "Winner's photo" field.\
Use the value, for example, in a REST API call.

Tips:

* Base64 increases the payload size.
* Use it only when the target system really needs inline content.
* Use the record-and-name form when a record has several attachments and you need one exact file.
* Use `loadFileAsBase64URL()` when the target expects a ready `data:` URL instead of raw Base64 text.

{% hint style="info" %}
Avoid storing large numbers of Base64 strings. If you need to keep them, use [createTextFile()](#build-files-with-createtextfile) to convert each string into a file. Then use [importFile()](#import-a-file-with-importfile) to save it as an attachment.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ninox.com/ninox-scripting/automate-your-workflows/work-with-functions/files-and-export.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
