file://¶
Filesystem endpoint with a broad surface — ~100 URI parameters covering polling, filtering, read-locking, sorting, atomic
writes, idempotent dedup, and on-completion strategies. Consumer polls
a directory and dispatches each discovered file into a route. Producer
op=write (default) writes the exchange body to a file with configurable
existing-file semantics, atomic temp-rename, chmod, fsync, jail, and
done-file signalling; producer op=read loads a file's raw bytes into
the body — the local-filesystem analog of s3://?operation=getObject,
and the native way to turn a path a caller names at runtime into bytes
for a downstream consumer (pdf://?op=extractText, xlsx://,
docling://, vlm://, …).
For the same surface against a remote server, see
ftp:// / ftps:// / sftp://.
URI shape¶
<directory> is the path the consumer polls / the producer writes
into. Relative paths are resolved to absolute at endpoint creation
(except the literal . which is preserved for back-compat). Producer
+ consumer share an Endpoint, so a to: file://outbox and a
from: file://outbox?delete=true operate on the same configured
directory.
Parameters¶
The exhaustive list lives in (*Component).Describe() —
pkg/component/file/file.go (function fileParamDescriptors). The
sections below summarise the surface; the per-parameter description is
the canonical authority.
Common¶
| Param | Type | Default | Description |
|---|---|---|---|
charset |
string | — | Character encoding for transcoding. |
doneFileName |
string | — | Marker file written by producer / waited for by consumer. Placeholders: ${file.name}, ${file.name.noext}. |
fileName |
string | — | Consumer: dynamic name filter. Producer: output filename (File-Language). |
Consumer¶
delete, move, moveFailed, preMove, noop, preSort,
recursive, sendEmptyMessageWhenIdle, bridgeErrorHandler,
directoryMustExist, extendedAttributes, includeHiddenDirs,
includeHiddenFiles, inProgressRepository, localWorkDirectory,
probeContentType, processStrategy, startingDirectoryMustExist,
startingDirectoryMustHaveAccess, stream.
Producer¶
op (write default / read; operation is an accepted alias),
appendChars, checksumFileAlgorithm, checksumWriteFile,
fileExist (Override / Append / Fail / Ignore / Move /
TryRename), flatten, jailStartingDirectory, moveExisting,
tempFileName, tempPrefix, allowNullBody, chmod,
chmodDirectory, eagerDeleteTargetFile, forceWrites,
keepLastModified.
op=read resolves the file to read per-exchange — from the
fileName= URI param, else the HelixFileName / CamelFileName
header — joins it against <directory>, and jail-checks it (a header
path can't escape the directory unless jailStartingDirectory=false).
It sets HelixFileName, HelixFilePath, HelixFileRelativePath,
HelixFileLength, and HelixFileLastModified on the message, exactly
like a polled file, and errors if no filename is supplied, the file is
missing, or the path is a directory.
Filter & sort¶
antExclude, antFilterCaseSensitive, antInclude,
eagerMaxMessagesPerPoll, exclude, excludeExt, filterDirectory,
filterFile, idempotent, idempotentEager, idempotentKey,
idempotentRepository, include, includeExt, maxDepth,
maxMessagesPerPoll, minDepth, move, shuffle, sortBy.
Read-lock¶
readLock (none / markerFile / changed / rename / fileLock
/ idempotent / idempotent-changed / idempotent-rename),
readLockCheckInterval, readLockDeleteOrphanLockFiles,
readLockIdempotentReleaseAsync, readLockIdempotentReleaseDelay,
readLockLoggingLevel, readLockMarkerFile, readLockMinAge,
readLockMinLength, readLockRemoveOnCommit, readLockRemoveOnRollback,
readLockTimeout.
Scheduler¶
backoffErrorThreshold, backoffIdleThreshold, backoffMultiplier,
delay, greedy, initialDelay, poll, repeatCount,
runLoggingLevel, scheduler (only none; Quartz/Spring are NOT
supported), startScheduler, useFixedDelay.
Misc¶
autoCreate, autoCreateStepwise, bufferSize,
copyAndDeleteOnRenameFail, renameUsingCopy, synchronous.
Body shape¶
Consumer¶
For each discovered file:
- In body — the file contents as
[]byte, or a lazy*exchange.StreamBodywhenstream=true. - In headers —
CamelFileName,CamelFileNameOnly,CamelFileParent,CamelFileAbsolute,CamelFileLength,CamelFileLastModified, plusContent-TypewhenprobeContentType=true.
Producer¶
op=writein body —[]byte,string, orio.Reader.allowNullBody=trueallows writing a zero-byte file.op=readout body — the file's raw[]byte. The input body is irrelevant; the path comes from thefileName=param or theHelixFileName/CamelFileNameheader.
The producer reads CamelFileName from the exchange (set by upstream
steps or inherited from the consumer) to determine the output filename
when fileName URI param isn't set.
Examples¶
Drop-folder consumer with idempotent dedup (auto-enabled when no completion strategy is set):
- id: inbox
from: file:///var/data/in?include=.*\.csv&delete=true&recursive=true
steps:
- to: direct://process-csv
Atomic producer with temp-rename and chmod:
- to: file:///var/data/out?fileName=${date:now:yyyy/MM/dd}/${exchangeId}.json&tempPrefix=.tmp&chmod=640&forceWrites=true
Read a file the caller names at runtime, then process it — the input
half of a document skill. The tool-call args arrive as the body
({"path": "report.pdf"}); a set-header moves the path to
HelixFileName, op=read loads the bytes, and pdf:// consumes them:
workflows:
- id: extract-doc
trigger: { uri: direct://extract }
steps:
- set-header: { name: HelixFileName, starlang: payload.path }
- target: "file:///var/docs?op=read" # path → raw bytes in body
- target: "pdf://x?op=extractText" # bytes → text
Read a JSON config file — a JSON body is auto-parsed, so its fields are directly addressable in the next step:
- target: "file:///etc/app?op=read&fileName=settings.json"
- transform:
starlang: '{ mode: payload.env, retries: payload.retries }'
Read-lock with changed strategy (don't pick up files still being
written):
Move processed files to a dated archive folder:
Done-file signalling (consumer waits for .ready, producer writes it):
- id: wait-for-done
from: file:///drop?doneFileName=${file:name.noext}.ready
- to: file:///publish?doneFileName=${file:name.noext}.ready
Behavior notes¶
- Idempotent auto-enables. When no completion strategy (
move,delete,noop,moveFailed) is configured, the consumer enablesidempotent=trueso a poll doesn't reprocess the same files forever. Override withidempotent=false. fileLockis local-only.readLock=fileLockuses OSflock/LockFile; it's rejected on the FTP family.- Jail.
jailStartingDirectory=true(default) refuses writes — andop=readreads — that resolve outside the configured starting directory. Point<directory>at a sandbox root and pass relative (or in-sandbox absolute) paths; setjailStartingDirectory=falseto read arbitrary absolute paths. op=readvs the consumer. The polling consumer (from:) reads files it discovers in a fixed directory;op=read(to:) reads a single file the route names at call time. Use the consumer to react to arriving files,op=readto fetch a specific caller-named file mid-route (e.g. backing a document skill's tool).stream=truehands a lazy*exchange.StreamBodydownstream instead of buffering the whole file — required for large files.- Param surface canonicalisation. Repeated
CreateEndpointcalls with the same directory + canonicalised param string return the same Endpoint. A different param set creates a new one.
Source¶
pkg/component/file/file.go— Component, Endpoint,fileParamDescriptors.pkg/component/file/{producer,consumer}.go— write / poll engines.pkg/component/file/{filter,sort,lock,lock_*}.go— filter, sort, read-lock strategies.pkg/component/file/{idempotent,inflight,file_lang}.go— dedup, in-progress tracking, File-Language expressions.pkg/component/file/streaming.go—stream=truebody type.