file uploads

This commit is contained in:
2025-07-13 07:17:40 +02:00
parent 11105c074f
commit 548dd7e9ef
14 changed files with 451 additions and 13 deletions

View File

@@ -2,16 +2,33 @@ mod create_directory;
mod delete_directory;
mod get_warren_path;
mod list_warrens;
mod upload_files;
use axum::routing::{delete, get, post};
use axum::{
extract::DefaultBodyLimit,
routing::{delete, get, post},
};
use crate::server::Router;
pub(super) fn router() -> Router {
Router::new()
.route("/", get(list_warrens::route))
.route("/{warren_id}", get(get_warren_path::route))
.route("/{warren_id}/{*rest}", get(get_warren_path::route))
.route("/{warren_id}/{*rest}", post(create_directory::route))
.route("/{warren_id}/{*rest}", delete(delete_directory::route))
.route("/{warren_id}/get", get(get_warren_path::route))
.route("/{warren_id}/get/{*rest}", get(get_warren_path::route))
.route("/{warren_id}/create/{*rest}", post(create_directory::route))
.route(
"/{warren_id}/delete/{*rest}",
delete(delete_directory::route),
)
.route(
"/{warren_id}/upload",
// 536870912 bytes = 0.5GB
post(upload_files::route).route_layer(DefaultBodyLimit::max(536870912)),
)
.route(
"/{warren_id}/upload/{*rest}",
// 536870912 bytes = 0.5GB
post(upload_files::route).route_layer(DefaultBodyLimit::max(536870912)),
)
}

View File

@@ -0,0 +1,34 @@
use axum::extract::{Multipart, Path, State};
use serde::Deserialize;
use uuid::Uuid;
use crate::{Result, api::AppState, warrens::Warren};
#[derive(Deserialize)]
pub(super) struct UploadPath {
warren_id: Uuid,
rest: Option<String>,
}
pub(super) async fn route(
State(state): State<AppState>,
Path(UploadPath { warren_id, rest }): Path<UploadPath>,
mut multipart: Multipart,
) -> Result<()> {
let warren = Warren::get(state.pool(), &warren_id).await?;
while let Ok(Some(field)) = multipart.next_field().await {
if field.name().is_none_or(|name| name != "files") {
continue;
};
let file_name = field.file_name().map(str::to_owned).unwrap();
let data = field.bytes().await.unwrap();
warren
.upload(state.serve_dir(), rest.as_deref(), &file_name, &data)
.await?;
}
Ok(())
}

View File

@@ -1,9 +1,24 @@
use std::path::Path;
use tokio::fs;
use tokio::{fs, io::AsyncWriteExt};
use crate::Result;
pub async fn write_file<P>(path: P, data: &[u8]) -> Result<()>
where
P: AsRef<Path>,
{
let mut file = fs::OpenOptions::new()
.write(true)
.create(true)
.open(path)
.await?;
file.write_all(data).await?;
Ok(())
}
pub async fn delete_file<P>(path: P) -> Result<()>
where
P: AsRef<Path>,

View File

@@ -8,7 +8,9 @@ use uuid::Uuid;
use crate::{
Result,
fs::{DirectoryEntry, FileType, create_dir, delete_dir, delete_file, get_dir_entries},
fs::{
DirectoryEntry, FileType, create_dir, delete_dir, delete_file, get_dir_entries, write_file,
},
};
#[derive(Debug, Clone, Serialize, FromRow)]
@@ -64,6 +66,20 @@ impl Warren {
FileType::Directory => delete_dir(path).await,
}
}
pub async fn upload(
&self,
serve_path: &str,
rest_path: Option<&str>,
file_name: &str,
data: &[u8],
) -> Result<()> {
let rest = format!("{}/{file_name}", rest_path.unwrap_or(""));
let path = build_path(serve_path, &self.path, Some(&rest));
write_file(path, data).await
}
}
fn build_path(serve_path: &str, warren_path: &str, rest_path: Option<&str>) -> PathBuf {
@@ -72,7 +88,7 @@ fn build_path(serve_path: &str, warren_path: &str, rest_path: Option<&str>) -> P
final_path.push(warren_path.strip_prefix("/").unwrap_or(warren_path));
if let Some(ref rest) = rest_path {
final_path.push(rest);
final_path.push(rest.strip_prefix("/").unwrap_or(rest));
}
final_path