File & Storage Operations
ZeyOS provides three distinct storage mechanisms, each designed for different use cases:
| Storage | Persistence | IDs | Best for |
|---|---|---|---|
file | Permanent | Path | Import/export files, configuration, structured data |
temp | Session / auto-cleanup | String | Intermediate processing, PDF templates, transient data |
bin | Permanent | Integer | Generated documents, cached exports, binary attachments |
File System (file namespace)
The file namespace provides commands for reading, writing, and managing files and directories within the application sandbox.
File system access is restricted to the application's sandbox. Operations outside the sandbox will fail.
Reading Files
file:read
Reads the entire content of a file into a variable.
<file:read var="content" filename="./data/config.json"/>
<output>$content</output>
file:readcsv
Reads a CSV file into a multidimensional array (rows[row][col]). The default delimiter is ; (semicolon) -- specify delimiter="," for standard comma-separated files.
<file:readcsv var="rows" filename="./data/contacts.csv" delimiter=","/>
<foreach var="rows" var_value="row">
<output>$row[0] - $row[1]&n;</output>
</foreach>
file:readjson
Reads a file and parses its content as JSON into a variable.
<file:readjson var="config" filename="./settings/config.json"/>
<output>API Key: $config.apiKey</output>
Writing Files
file:write
Writes content to a file, creating or overwriting it.
<file:write filename="./data/output.txt">Report generated at $timestamp</file:write>
file:writecsv
Writes a multidimensional array as CSV to a file.
<array var="rows">
<array><item>Name</item><item>Email</item></array>
</array>
<file:writecsv var="rows" filename="./data/export.csv" delimiter=","/>
file:writejson
Writes the JSON representation of a variable to a file.
<array var="config">
<item key="version">2</item>
<item key="debug">false</item>
</array>
<file:writejson var="config" filename="./data/config.json"/>
file:append
Appends content to a file without overwriting. Creates the file if it does not exist.
<file:append filename="./logs/app.log">[$timestamp] $message&n;</file:append>
File Information
file:exists
Checks whether a file or directory exists. Returns the canonicalized path on success, or FALSE if not found.
<file:exists var="exists" filename="./data/config.json"/>
<is var="exists" type="false">
<output>File does not exist!</output>
</is>
file:typeof
Returns the type of a file system entry: file, dir, link, or undefined.
<file:typeof var="type" filename="./data"/>
<output>Type: $type</output>
file:status
Returns detailed status information (size, timestamps, etc.) about a file or directory.
<file:status var="info" filename="./data/report.pdf"/>
<output>Size: $info.size bytes, Modified: $info.mtime</output>
file:pathinfo
Parses a filename into components: dirname, basename, extension, and filename.
<file:pathinfo var="info" filename="./data/report.xlsx"/>
<output>Dir: $info.dirname, Ext: $info.extension, Name: $info.filename</output>
File Management
file:delete
Deletes a file. This operation is irreversible.
<file:exists var="exists" filename="./data/temp.txt"/>
<is var="exists" type="non-false">
<file:delete filename="./data/temp.txt"/>
</is>
file:rename
Renames or moves a file or directory.
<file:rename oldname="./data/draft.txt" newname="./data/final.txt"/>
file:link
Creates a symbolic link pointing to a target path.
file:send
Sends a file directly to the client as the HTTP response body (for serving downloads).
<file:send filename="./data/report.pdf"/>
Directory Operations
file:listdir
Lists all filenames within a directory.
<file:listdir var="files" dirname="./data"/>
<foreach var="files" var_value="filename">
<output>$filename&n;</output>
</foreach>
file:glob
Finds all pathnames matching a wildcard pattern (?, *, [...]).
<file:glob var="csvfiles" pattern="./data/*.csv"/>
<foreach var="csvfiles" var_value="path">
<file:pathinfo var="info" filename="$path"/>
<output>Found CSV: $info.filename&n;</output>
</foreach>
file:makedir
Creates a new directory. Parent directories are created recursively.
<file:makedir dirname="./data/exports/2024"/>
file:removedir
Removes an empty directory. Delete all files within it first.
Temporary Data Store (temp namespace)
The temp namespace provides temporary storage that persists across requests within the same application context. When you write data with temp:write, it returns a string ID that you use for all subsequent operations. Temporary files are automatically cleaned up by ZeyOS.
<!-- Write temporary data — returns an ID -->
<temp:write var="temp_id">Temporary content</temp:write>
<!-- Read it back -->
<temp:read var="content" id="$temp_id"/>
<!-- Get the filesystem path (essential for pdf:templates) -->
<temp:path var="filepath" id="$temp_id"/>
<!-- Delete when done -->
<temp:delete id="$temp_id"/>
Using temp for PDF templates
The most common use of temp:path is bridging between iXML resources and the PDF engine. Since pdf:templates requires a filesystem path, you store resource content in temp and pass the path:
<include id="letterhead" type="resource" var="template_data"/>
<temp:write var="temp_id">$template_data</temp:write>
<temp:path var="template_path" id="$temp_id"/>
<pdf:document var="pdf">
<pdf:section>
<pdf:templates filename="$template_path">
<pdf:template source="1" target="1"/>
</pdf:templates>
<pdf:body>
<pdf:block>Content on letterhead</pdf:block>
</pdf:body>
</pdf:section>
</pdf:document>
temp:write | temp:read | temp:path | temp:delete
Binary Data Store (bin namespace)
The bin namespace provides permanent binary storage. Unlike temp, binary data persists indefinitely and uses integer IDs. Use it when you need to store generated files (PDFs, exports, images) that should be retrievable later.
<!-- Store binary data — returns an integer ID -->
<bin:write var="bin_id">$pdf_data</bin:write>
<!-- Retrieve later -->
<bin:read var="retrieved" id="$bin_id"/>
A common pattern is generating a PDF and storing it for later download:
<pdf:document var="pdf">
<!-- ... PDF content ... -->
</pdf:document>
<!-- Store the generated PDF permanently -->
<bin:write var="doc_id">$pdf</bin:write>
<!-- Save the bin ID alongside the entity for later retrieval -->
<extdata:set entity="transactions" id="$transaction_id">
<extdata:data field="invoice_pdf">$doc_id</extdata:data>
</extdata:set>
Practical Patterns
File-based Import Workflow
<!-- Find all CSV files in the import directory -->
<file:glob var="imports" pattern="./data/imports/*.csv"/>
<foreach var="imports" var_value="filepath">
<file:pathinfo var="info" filename="$filepath"/>
<output>Processing: $info.basename&n;</output>
<!-- Read and parse the CSV -->
<file:readcsv var="rows" filename="$filepath" delimiter=","/>
<!-- Process rows (skip header) -->
<set var="i">0</set>
<foreach var="rows" var_value="row">
<if value1="$i" value2="0" func=">">
<output> Row $i: $row[0] - $row[1]&n;</output>
</if>
<set var="i">$(($i + 1))</set>
</foreach>
<!-- Archive processed file -->
<file:rename oldname="$filepath" newname="./data/archive/$info.basename"/>
</foreach>
JSON Configuration Loading
<file:exists var="exists" filename="./settings/config.json"/>
<is var="exists" type="false">
<!-- Create default config -->
<array var="config">
<item key="pageSize">25</item>
<item key="locale">en</item>
</array>
<file:writejson var="config" filename="./settings/config.json"/>
</is>
<is var="exists" type="non-false">
<file:readjson var="config" filename="./settings/config.json"/>
</is>
<output>Page size: $config.pageSize</output>
CSV Import with Database Insert
<file:readcsv var="rows" filename="import/contacts.csv" delimiter="," header="1"/>
<foreach var="rows" var_value="row">
<db:set entity="contacts">
<db:data field="firstname">$row.firstname</db:data>
<db:data field="lastname">$row.lastname</db:data>
<db:data field="email">$row.email</db:data>
</db:set>
</foreach>