Skip to content

Commit

Permalink
Create user specific directory for uploads
Browse files Browse the repository at this point in the history
Update UI to reflect aborted uploads
  • Loading branch information
dormant-user committed Mar 10, 2024
1 parent 13c1a66 commit fbbdb43
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 25 deletions.
40 changes: 16 additions & 24 deletions src/routes/upload.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use std::time::Instant;

use actix_multipart::Multipart;
use actix_web::{http, HttpRequest, HttpResponse, web};
Expand All @@ -28,7 +26,8 @@ use crate::{constant, routes, squire};
/// # Returns
///
/// * `200` - Plain HTTPResponse indicating that the file was uploaded.
/// * `401` - HTTPResponse with JSON payload indicating the problem uploading file.
/// * `422` - HTTPResponse with JSON object indicating that the payload was incomplete.
/// * `400` - HTTPResponse with JSON object indicating that the payload was invalid.
#[post("/upload")]
pub async fn save_files(request: HttpRequest,
mut payload: Multipart,
Expand All @@ -39,40 +38,38 @@ pub async fn save_files(request: HttpRequest,
if !auth_response.ok {
return routes::auth::failed_auth(auth_response, &config);
}
let source_path = Path::new("uploads");
let upload_path = config.media_source.join(&auth_response.username);
while let Some(item) = payload.next().await {
match item {
Ok(mut field) => {
let filename = field.content_disposition().get_filename().unwrap();
let mut destination = File::create(source_path.join(filename)).unwrap();
let start = Instant::now();
log::info!("Downloading '{}'", &filename);
let mut destination = File::create(&upload_path.join(filename)).unwrap();
log::info!("Downloading '{}' - uploaded by {}", &filename, &auth_response.username);
while let Some(fragment) = field.next().await {
match fragment {
Ok(chunk) => {
destination.write_all(&chunk).unwrap();
}
Err(err) => {
let error = format!("Error processing field: {}", err);
log::error!("{}", &error);
return HttpResponse::InternalServerError().json(error);
// User might have aborted file upload
let error = format!("Error processing chunk: {}", err);
log::warn!("{}", &error);
return HttpResponse::UnprocessableEntity().json(error);
}
}
}
// todo: Remove this or set to debug
log::info!("Download completed in {}s", start.elapsed().as_secs())
}
Err(err) => {
let error = format!("Error processing field: {}", err);
log::error!("{}", &error);
return HttpResponse::InternalServerError().json(error);
return HttpResponse::BadRequest().json(error);
}
}
}
HttpResponse::Ok().finish()
}

/// Handles requests for the '/upload' endpoint, serving the file upload template.
/// Handles requests for the `/upload` endpoint, serving the file upload template.
///
/// # Arguments
///
Expand All @@ -95,20 +92,15 @@ pub async fn upload_files(request: HttpRequest,
if !auth_response.ok {
return routes::auth::failed_auth(auth_response, &config);
}
// todo: Create user specific directories and upload there instead
let upload_path = Path::new("uploads");
let upload_path = config.media_source.join(&auth_response.username);
if !upload_path.exists() {
match std::fs::create_dir("uploads") {
Ok(_) => {
log::info!("Created uploads directory successfully");
}
Err(err) => {
log::error!("{}", err);
}
match std::fs::create_dir(&upload_path) {
Ok(_) => log::info!("'{}' has been created", &upload_path.to_str().unwrap()),
Err(err) => log::error!("{}", err)
}
}
let landing = template.get_template("upload").unwrap();
HttpResponse::build(http::StatusCode::OK)
.content_type("text/html; charset=utf-8")
.body(landing.render(minijinja::context!()).unwrap()) // no arguments to render
.body(landing.render(minijinja::context!(USER => auth_response.username)).unwrap())
}
12 changes: 11 additions & 1 deletion src/templates/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ pub fn get_content() -> String {
<div class="header-section">
<h1>Upload Files</h1>
<p>Only PDF, Images & Videos are allowed.</p>
<br>
<p>Uploaded files will be stored in '{{ USER }}' directory</p>
</div>
<div class="drop-section">
<div class="col">
Expand Down Expand Up @@ -420,7 +422,15 @@ pub fn get_content() -> String {
http.open('POST', window.location.origin + '/upload', true);
http.send(data)
li.querySelector('.cross').onclick = () => http.abort()
http.onabort = () => li.remove()
http.onabort = () => {
let crossElement = li.querySelector('.cross');
// Insert a red cross sign
crossElement.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" class="cross-solid" height="20" width="20"><path d="m5.979 14.917-.854-.896 4-4.021-4-4.062.854-.896 4.042 4.062 4-4.062.854.896-4 4.062 4 4.021-.854.896-4-4.063Z" stroke="red" stroke-width="2"></path></svg>';
let context = li.querySelector('.file-name');
let spanElement = context.querySelector('span');
// Change uploaded percentage into a text
spanElement.innerHTML = 'ABORTED!!';
}
}
// find icon for file
Expand Down

0 comments on commit fbbdb43

Please sign in to comment.