struct
Amber::Router::File
- Amber::Router::File
- Struct
- Value
- Object
Overview
A file uploaded in a multipart request, held in a tempfile that Amber owns until the request finishes.
During the action, read the upload through #file, which opens the
tempfile on first use, or through #open_tempfile. When the request
finishes, Amber closes that handle and deletes the tempfile.
To keep an upload beyond the request, transfer it during the action:
# Move it to permanent storage; Amber no longer deletes it.
stored_path = params.files["avatar"].move_to("storage/avatars/#{user.id}.png")
# Or keep the tempfile where it is and take over deleting it, for
# example before handing the path to a background job.
ProcessUpload.new(params.files["report"].retain!).enqueue
Each method transfers ownership once: after #move_to or #retain!,
Amber's cleanup leaves the path alone.
Defined in:
amber/router/file.crConstant Summary
-
Log =
::Log.for(self) -
UPLOAD_DIRECTORY =
::File.join(Dir.tempdir, upload_directory_name) -
The preferred upload directory: one per user, which every worker and every restart of the app reuses, so directories never pile up.
Constructors
-
.new(upload, max_bytes : Int64 | Nil = nil)
Copies the upload into a newly created tempfile.
Class Method Summary
-
.retry_leftover_deletions : Nil
Deletes the tempfiles
discardcould not, when their paths still name the files Amber created; Amber calls it when a request finishes. -
.safe_extension(filename : String | Nil) : String
Returns the extension of filename when it is a dot followed by one to sixteen ASCII letters or digits, and an empty string otherwise.
-
.upload_directory : String
Returns a directory only this user can enter, so no other local user can create or replace files in it: a real directory, owned by this user, with mode 0700.
Instance Method Summary
- #creation_time : Time | Nil
-
#delete_tempfile : Nil
Amber's cleanup, run when the request finishes or its parse fails.
-
#file : ::File
A read handle on the upload, opened on first use and positioned at its start.
- #filename : String | Nil
- #headers : HTTP::Headers
- #modification_time : Time | Nil
-
#move_to(destination : String | Path) : String
Moves the upload to destination, replacing any file there, and returns that path.
-
#open_tempfile(& : ::File -> T) : T forall T
Opens the tempfile for reading after checking that its path still names the file Amber created, yields the handle, and closes it.
-
#owned_by_amber? : Bool
Whether Amber still owns the tempfile and will delete it when the request finishes.
-
#path : String
The path of the tempfile Amber created.
- #read_time : Time | Nil
-
#retain! : String
Keeps the tempfile at
#pathafter the request and returns that path. - #size : UInt64 | Nil
Constructor Detail
Copies the upload into a newly created tempfile. With max_bytes, a
larger upload raises Amber::Exceptions::ParameterLimitExceeded; on
any failure the tempfile is removed. #size is the number of bytes
copied; the client's declared size is ignored.
Class Method Detail
Deletes the tempfiles discard could not, when their paths still name
the files Amber created; Amber calls it when a request finishes. Files
that still cannot be deleted are kept for the next call.
Returns the extension of filename when it is a dot followed by one to sixteen ASCII letters or digits, and an empty string otherwise.
Returns a directory only this user can enter, so no other local user can create or replace files in it: a real directory, owned by this user, with mode 0700.
It is UPLOAD_DIRECTORY, created when missing. If another user has
claimed that path in a shared temporary directory, this process uses a
new directory with an unpredictable name instead, and keeps using it.
Instance Method Detail
Amber's cleanup, run when the request finishes or its parse fails.
Closes the handle #file opened. When Amber still owns the tempfile,
it deletes the path if, when checked, it still names the file Amber
created (same device and inode, symlinks not followed), then gives up
ownership. A failed delete raises and leaves ownership in place, so a
later call can retry it. The check and the unlink are two system calls, so code
running as this user that swaps the path between them can still lose
the file it put there; the private upload directory keeps every other
user out. To keep an upload, transfer it with #move_to or #retain!,
which stop this cleanup entirely.
A handle that fails to close does not stop the deletion.
A read handle on the upload, opened on first use and positioned at its
start. Amber closes it when the request finishes. Raises IO::Error
after #move_to, or when the path no longer names the tempfile.
Moves the upload to destination, replacing any file there, and
returns that path. From then on the file belongs to the caller:
Amber's cleanup leaves it alone, and #file raises.
Across file systems the upload is copied to a new file beside destination and renamed into place only after the copy succeeds; the tempfile is deleted only after that rename. If the copy fails, the partial copy is removed, destination is left as it was, and Amber still owns the tempfile.
Opens the tempfile for reading after checking that its path still names the file Amber created, yields the handle, and closes it.
Whether Amber still owns the tempfile and will delete it when the request finishes.