logo
pub enum TempFile<'v> {
    // some variants omitted
}
Expand description

A data and form guard that streams data into a temporary file.

TempFile is a data and form field (both value and data fields) guard that streams incoming data into file in a temporary location. The file is deleted when the TempFile handle is dropped unless it is persisted with TempFile::persist_to() or copied with TempFile::copy_to().

Hazards

Temporary files are cleaned by system file cleaners periodically. While an attempt is made not to delete temporary files in use, detection of when a temporary file is being used is unreliable. As a result, a time-of-check to time-of-use race condition from the creation of a TempFile to the persistence of the TempFile may occur. Specifically, the following sequence may occur:

  1. A TempFile is created at random path foo.
  2. The system cleaner removes the file at path foo.
  3. Another application creates a file at path foo.
  4. The TempFile, ostesnsibly at path, foo, is persisted unexpectedly with contents different from those in step 1.

To safe-guard against this issue, you should ensure that your temporary file cleaner, if any, does not delete files too eagerly.

Configuration

TempFile is configured via the following config parameters:

NameDefaultDescription
temp_direnv::temp_dir()Directory for temporary file storage.
limits.file1MiBDefault limit for all file extensions.
limits.file/$extN/ALimit for files with extension $ext.

When used as a form guard, the extension $ext is identified by the form field’s Content-Type (ContentType::extension()). When used as a data guard, the extension is identified by the Content-Type of the request, if any. If there is no Content-Type, the limit file is used.

Cappable

A data stream can be partially read into a TempFile even if the incoming stream exceeds the data limit via the Capped<TempFile> data and form guard.

Examples

Data Guard

use rocket::fs::TempFile;

#[post("/upload", data = "<file>")]
async fn upload(mut file: TempFile<'_>) -> std::io::Result<()> {
    file.persist_to("/tmp/complete/file.txt").await?;
    Ok(())
}

Form Field

use rocket::fs::TempFile;
use rocket::form::Form;

#[derive(FromForm)]
struct Upload<'f> {
    upload: TempFile<'f>
}

#[post("/form", data = "<form>")]
async fn upload(mut form: Form<Upload<'_>>) -> std::io::Result<()> {
    form.upload.persist_to("/tmp/complete/file.txt").await?;
    Ok(())
}

See also the Capped documentation for an example of Capped<TempFile> as a data guard.

Implementations

Persists the temporary file, moving it to path. If a file exists at the target path, self will atomically replace it. self.path() is updated to path.

This method does not create a copy of self, nor a new link to the contents of self: it renames the temporary file to path and marks it as non-temporary. As a result, this method cannot be used to create multiple copies of self. To create multiple links, use std::fs::hard_link() with path as the src after calling this method.

Cross-Device Persistence

Attemping to persist a temporary file across logical devices (or mount points) will result in an error. This is a limitation of the underlying OS. Your options are thus:

  1. Store temporary file in the same logical device.

    Change the temp_dir configuration parameter to be in the same logical device as the permanent location. This is the preferred solution.

  2. Copy the temporary file using TempFile::copy_to() or TempFile::move_copy_to() instead.

    This is a full copy of the file, creating a duplicate version of the file at the destination. This should be avoided for performance reasons.

Example
use rocket::fs::TempFile;

#[post("/", data = "<file>")]
async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {
    file.persist_to(&some_path).await?;
    assert_eq!(file.path(), Some(&*some_path));

    Ok(())
}

Persists the temporary file at its temporary path and creates a full copy at path. The self.path() is not updated, unless no temporary file existed prior, and the temporary file is not removed. Thus, there will be two files with the same contents.

Unlike TempFile::persist_to(), this method does not incur cross-device limitations, at the performance cost of a full copy. Prefer to use persist_to() with a valid temp_dir configuration parameter if no more than one copy of a file is required.

Example
use rocket::fs::TempFile;

#[post("/", data = "<file>")]
async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {
    file.copy_to(&some_path).await?;
    file.copy_to(&some_other_path).await?;
    assert_eq!(file.path(), Some(&*some_path));

    Ok(())
}

Persists the temporary file at its temporary path, creates a full copy at path, and then deletes the temporary file. self.path() is updated to path.

Like TempFile::copy_to() and unlike TempFile::persist_to(), this method does not incur cross-device limitations, at the performance cost of a full copy and file deletion. Prefer to use persist_to() with a valid temp_dir configuration parameter if no more than one copy of a file is required.

Example
use rocket::fs::TempFile;

#[post("/", data = "<file>")]
async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {
    file.move_copy_to(&some_path).await?;

    Ok(())
}

Returns the size, in bytes, of the file.

This method does not perform any system calls.

use rocket::fs::TempFile;

#[post("/", data = "<file>")]
fn handler(file: TempFile<'_>) {
    let file_len = file.len();
}

Returns the path to the file if it is known.

Once a file is persisted with TempFile::persist_to(), this method is guaranteed to return Some. Prior to this point, however, this method may return Some or None, depending on whether the file is on disk or partially buffered in memory.

use rocket::fs::TempFile;

#[post("/", data = "<file>")]
async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {
    file.persist_to(&some_path).await?;
    assert_eq!(file.path(), Some(&*some_path));

    Ok(())
}

Returns the sanitized file name as specified in the form field.

A multipart data form field can optionally specify the name of a file. A browser will typically send the actual name of a user’s selected file in this field, but clients are also able to specify any name, including invalid or dangerous file names. This method returns a sanitized version of that value, if it was specified, suitable and safe for use as a permanent file name.

Note that you will likely want to prepend or append random or user-specific components to the name to avoid collisions; UUIDs make for a good “random” data.

See FileName::as_str() for specifics on sanitization.

use rocket::fs::TempFile;

#[post("/", data = "<file>")]
async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {
    if let Some(name) = file.name() {
        // Because of Rocket's sanitization, this is safe.
        file.persist_to(&some_dir.join(name)).await?;
    }

    Ok(())
}

Returns the raw name of the file as specified in the form field.

use rocket::fs::TempFile;

#[post("/", data = "<file>")]
async fn handle(mut file: TempFile<'_>) {
    let raw_name = file.raw_name();
}

Returns the Content-Type of the file as specified in the form field.

A multipart data form field can optionally specify the content-type of a file. A browser will typically sniff the file’s extension to set the content-type. This method returns that value, if it was specified.

use rocket::fs::TempFile;

#[post("/", data = "<file>")]
fn handle(file: TempFile<'_>) {
    let content_type = file.content_type();
}

Trait Implementations

Formats the value using the given formatter. Read more

The associated error to be returned when the guard fails.

Asynchronously validates, parses, and converts an instance of Self from the incoming request body data. Read more

Returns a default value, if any exists, to be used during lenient parsing when the form field is missing. Read more

Parse a value of T from a form value field. Read more

Parse a value of T from a form data field. Read more

The length of the value.

Convert len into u64.

The zero value for L.

The length of the value.

Convert len into u64.

The zero value for L.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more

Instruments this type with the current Span, returning an Instrumented wrapper. Read more

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Converts self into a collection.

Should always be Self

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more