Skip to main content

store

Function store 

Source
pub fn store(
    ctx: &Ctx,
    prefix: &str,
    upload: Upload,
) -> impl Future<Output = Result<Attachment>> + Send + use<>
Expand description

Stores an Upload in R2 under a new random key starting with prefix, and returns the Attachment to save.

The key is <prefix>/<22 random characters> (posts/avatar/...), never derived from the file name; the file name and content type are cleaned up like store_bytes’s. Check the upload with Validator::file first, and save the attachment with columns; if saving the row fails, delete the new key.

Free plan: one R2 class A operation (1M free per month); copying 10 MB to R2 takes about 0.15 ms of CPU. Stored files count towards the 10 GB-month of free storage.

§Errors

Error::Internal (500) when the STORAGE binding is missing (the message shows the STORAGE entry to add to cloudflare.config.ts) or the R2 write fails.

§Examples

use axum::extract::State;
use ocre::storage::{self, Multipart, Rules};
use ocre::{Ctx, Error, Result, Validator};

const DOCUMENT: Rules = Rules { max_bytes: 10 * 1024 * 1024, content_types: &["application/pdf"] };

// PUT /documents with `curl -X PUT -F file=@spec.pdf`.
async fn upload(State(ctx): State<Ctx>, Multipart(mut form): Multipart<{ 11 * 1024 * 1024 }>) -> Result<String> {
    let file = form.file("file").ok_or_else(|| Error::bad_request("Send the file as `file`"))?;
    Validator::new().file("file", &file, &DOCUMENT).finish()?;
    let document = storage::store(&ctx, "documents/file", file).await?;
    Ok(document.key)
}