New on the blog: File Uploads in Wheels 4.0, the I...
# wheels-dev
p
New on the blog: File Uploads in Wheels 4.0, the Idiomatic Way. <https://blog.wheels.dev/posts/file-uploads-in-wheels-4/ > Wheels 4.0 has no ActiveStorage-style attachment system — no
hasAttachment
, no upload service, no
params.file
. And that's fine. The honest idiomatic flow is five steps, and this post walks every one end to end. What it covers: • The multipart trap —
startFormTag
does NOT auto-add
enctype
just because a
fileField
is on the form. Default is
multipart=false
. Forget
multipart=true
and the upload fails silently — no error, file posts as plain text. This eats more uploads than everything else combined. •
fileField
vs
fileFieldTag
— bound (
user[avatar]
) vs unbound (
document
) field names, and why the name is your contract with the controller. • The controller — native CFML
cffile action="upload"
(Wheels has zero upload wrapper),
nameConflict="makeUnique"
, and copying the result onto
params.user
so the model can validate it. • Validation —
validatesFormatOf
over the stored string + a custom
validate()
callback for size/MIME, because validators can't see multipart uploads. •
sendFile
— the one direction with a real Wheels helper, with built-in path-traversal protection. Plus a "Sharp edges" section of real, source-confirmed gotchas.