Skip to content

Commit 5e27b8c

Browse files
committed
refactor file service
1 parent fcb7afa commit 5e27b8c

File tree

2 files changed

+44
-43
lines changed

2 files changed

+44
-43
lines changed

api/src/router/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use axum::{
88
pub fn get_router(state: ApiState) -> Router {
99
Router::new()
1010
.route("/healthz", get(handler::health_check))
11-
.route("/upload/:filename", post(handler::file::upload))
11+
.route("/upload", post(handler::file::upload))
1212
.route("/info/:code/:filename", get(handler::file::info))
1313
.route("/:code/:filename", get(handler::file::download))
1414
.route("/:code/:filename", delete(handler::file::delete))

api/src/service/file.rs

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::error::{ApiError, ApiResult, ToApiResult};
2+
use axum::extract::multipart::Field;
23
use axum::extract::Multipart;
34
use chrono::{DateTime, Utc};
45
use futures_util::TryStreamExt;
@@ -17,7 +18,7 @@ pub async fn store(
1718
state: &ApiState,
1819
query: &UploadParamQuery,
1920
auth: Option<String>,
20-
multipart: Multipart,
21+
mut multipart: Multipart,
2122
) -> ApiResult<(FilePath, DateTime<Utc>)> {
2223
let auth = hash(auth)?;
2324
let expire_secs = query
@@ -36,31 +37,52 @@ pub async fn store(
3637
auth,
3738
count_downloads: 0,
3839
};
39-
let path = loop {
40-
let code = crate::util::string::generate_random_string(code_length);
41-
let path = FilePath {
42-
code,
43-
file_name: "TODO".to_string(),
44-
};
45-
if state.db.exist(&path)? {
40+
while let Ok(Some(field)) = multipart.next_field().await {
41+
let file_name = if let Some(file_name) = field.file_name() {
42+
crate::util::file_name::validate(file_name)?;
43+
file_name.to_owned()
44+
} else {
4645
continue;
47-
}
48-
match state.db.store(path.clone(), meta.clone()).await {
49-
Ok(_) => break path,
50-
Err(ApiError::ResourceExists(e)) => {
51-
debug!("Key already exist: {e}");
46+
};
47+
let path = loop {
48+
let code = crate::util::string::generate_random_string(code_length);
49+
let path = FilePath {
50+
code,
51+
file_name: file_name.clone(),
52+
};
53+
if state.db.exist(&path)? {
5254
continue;
5355
}
54-
Err(e) => return Err(e),
56+
match state.db.store(path.clone(), meta.clone()).await {
57+
Ok(_) => break path,
58+
Err(ApiError::ResourceExists(e)) => {
59+
debug!("Key already exist: {e}");
60+
continue;
61+
}
62+
Err(e) => return Err(e),
63+
}
64+
};
65+
let file_path = path.fs_path(&state.config.fs.base_dir);
66+
if let Err(e) = store_stream(&file_path, field).await {
67+
state.db.delete(path).await?;
68+
return Err(e);
5569
}
56-
};
57-
let file_path = path.fs_path(&state.config.fs.base_dir);
58-
if let Err(e) = store_stream(&file_path, multipart).await {
59-
state.db.delete(path).await?;
60-
return Err(e);
70+
state.db.flush().await?;
71+
return Ok((path, expiration_date));
6172
}
62-
state.db.flush().await?;
63-
Ok((path, expiration_date))
73+
Err(ApiError::BadRequest("multpart is empty".to_string()))
74+
}
75+
76+
pub async fn store_stream(file_path: &PathBuf, field: Field<'_>) -> ApiResult<()> {
77+
let body_with_io_error = field.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err));
78+
let body_reader = StreamReader::new(body_with_io_error);
79+
futures_util::pin_mut!(body_reader);
80+
if let Some(p) = file_path.parent() {
81+
tokio::fs::create_dir_all(p).await?;
82+
}
83+
let mut file = BufWriter::new(File::create(file_path).await?);
84+
tokio::io::copy(&mut body_reader, &mut file).await?;
85+
Ok(())
6486
}
6587

6688
pub async fn info(
@@ -132,27 +154,6 @@ pub async fn delete(
132154
Ok(())
133155
}
134156

135-
pub async fn store_stream(file_path: &PathBuf, mut multipart: Multipart) -> ApiResult<()> {
136-
while let Ok(Some(field)) = multipart.next_field().await {
137-
let _file_name = if let Some(file_name) = field.file_name() {
138-
file_name.to_owned()
139-
} else {
140-
continue;
141-
};
142-
let body_with_io_error =
143-
field.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err));
144-
let body_reader = StreamReader::new(body_with_io_error);
145-
futures_util::pin_mut!(body_reader);
146-
if let Some(p) = file_path.parent() {
147-
tokio::fs::create_dir_all(p).await?;
148-
}
149-
let mut file = BufWriter::new(File::create(file_path).await?);
150-
tokio::io::copy(&mut body_reader, &mut file).await?;
151-
}
152-
153-
Ok(())
154-
}
155-
156157
pub async fn read_file(file_path: &PathBuf) -> ApiResult<ServeFile> {
157158
Ok(ServeFile::new(file_path))
158159
}

0 commit comments

Comments
 (0)