file uploads
This commit is contained in:
@@ -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)),
|
||||
)
|
||||
}
|
||||
|
||||
34
backend/src/api/warrens/upload_files.rs
Normal file
34
backend/src/api/warrens/upload_files.rs
Normal 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(())
|
||||
}
|
||||
@@ -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>,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user