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)
}