Skip to content

Commit 23402d3

Browse files
committed
add endpoint to upload images without timestamp
1 parent 1673bf2 commit 23402d3

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"rust-analyzer.checkOnSave": false
3+
}

src/main.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ async fn main() {
3737
let app = Router::new()
3838
.route("/", get(|| async move { "welcome to Image upload api" }))
3939
.route("/upload", post(upload_image))
40+
.route("/upload/master", post(upload_image_no_timestamp))
4041
.layer(cors_layer)
4142
.layer(Extension(aws_s3_client))
4243
.layer(axum::middleware::from_fn(log_request_ip));
@@ -113,3 +114,63 @@ async fn upload_image(
113114
// send the urls in response
114115
Ok(Json(serde_json::json!(res)))
115116
}
117+
118+
119+
async fn upload_image_no_timestamp(
120+
Extension(s3_client): Extension<Client>,
121+
mut files: Multipart,
122+
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
123+
// get the name of aws bucket from env variable
124+
let bucket = std::env::var("AWS_S3_BUCKET").unwrap_or_else(|_| "my-bucket-name".to_owned());
125+
// if you have a public url for your bucket, place it as ENV variable BUCKET_URL
126+
let bucket_url = std::env::var("BUCKET_URL").unwrap_or_else(|_| bucket.to_owned());
127+
// if a sub folder path is set in environment then get that else set a default sub path
128+
let sub_path = std::env::var("BUCKET_SUB_PATH").unwrap_or_else(|_| "uploaded_images".to_owned());
129+
// we are going to store the respose in HashMap as filename: url => key: value
130+
let mut res = HashMap::new();
131+
while let Some(file) = files.next_field().await.unwrap() {
132+
// this is the name which is sent in formdata from frontend or whoever called the api, i am
133+
// using it as category, we can get the filename from file data
134+
let category = file.name().unwrap().to_string();
135+
// name of the file with extention
136+
let name = file.file_name().unwrap().to_string();
137+
// file data
138+
let data = file.bytes().await.unwrap();
139+
// the request can control where to save the image on AWS S3
140+
let request_path = if category.trim().is_empty() {"".to_owned()} else {format!("{}/", &category.trim_end_matches('/'))};
141+
// the path of file to store on aws s3 with file name and extention
142+
// timestamp_category_filename => 14-12-2022_01:01:01_customer_somecustomer.jpg
143+
let key = format!(
144+
"{}/images/{}_{}_{}",
145+
sub_path,
146+
&request_path,
147+
&category,
148+
&name
149+
);
150+
151+
// send Putobject request to aws s3
152+
let _resp = s3_client
153+
.put_object()
154+
.bucket(&bucket)
155+
.key(&key)
156+
.body(data.into())
157+
.send()
158+
.await
159+
.map_err(|err| {
160+
dbg!(err);
161+
(
162+
StatusCode::INTERNAL_SERVER_ERROR,
163+
Json(serde_json::json!({"err": "an error occured during image upload"})),
164+
)
165+
})?;
166+
dbg!(_resp);
167+
res.insert(
168+
// concatinating name and category so even if the filenames are same it will not
169+
// conflict
170+
format!("{}_{}", &name, &category),
171+
format!("{}/{}", bucket_url, key),
172+
);
173+
}
174+
// send the urls in response
175+
Ok(Json(serde_json::json!(res)))
176+
}

0 commit comments

Comments
 (0)