Newer
Older
use crate::static_files::upload::*;
use crate::website::WebSite;
use actix_multipart::Multipart;
use actix_web::{
delete, get, post, web,
web::{Data, Path},
HttpResponse, Responder,
};
use futures::StreamExt;
use std::{
fs::{remove_file, File},
io::Write,
};
pub async fn favicon(website: web::Data<std::sync::Mutex<WebSite>>) -> impl Responder {
let static_files_manager = &website.lock().unwrap().static_files_manager;
NamedFile::open(static_files_manager.dir.join("default").join("favicon.ico"))
}
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
fn upload_data_from_multipart_field(
field: &actix_multipart::Field,
) -> Result<UploadFileData, String> {
match field.content_disposition().get_filename() {
Some(fname) => match file_ext(&fname.to_string()) {
Ok(ext) => Ok(UploadFileData {
up_type: upload_type_from_file_ext(&ext),
filename: fname.to_owned(),
}),
Err(msg) => return Err(msg),
},
None => Err("Couldn't retrieve file extension".to_string()),
}
}
async fn write_uploaded_file(
website: &WebSite,
field: &mut actix_multipart::Field,
filename: &String,
upload_type: UploadFileType,
) -> Result<String, String> {
let root = &website.static_files_manager.dir;
let sub_dir = dirname_from_type(&upload_type);
let filepath = root.join(sub_dir).join(&filename);
match File::create(&filepath) {
Err(e) => Err(format!("Error creating file {:?} : {:?}", filepath, e)),
Ok(mut f) => {
// Field in turn is stream of *Bytes* object
while let Some(chunk) = field.next().await {
match chunk {
Ok(chunk) => {
if f.write_all(&chunk).is_err() {
remove_file(&filepath).unwrap();
return Err("Error writing chunk".to_string());
}
}
Err(e) => {
return Err(format!("Error writing file {} : {:?}", filename, e));
}
}
}
Ok(filepath.into_os_string().into_string().unwrap())
}
}
}
#[post("/post-files")]
pub async fn post_files(
website: Data<std::sync::Mutex<WebSite>>,
mut payload: Multipart,
) -> impl Responder {
let mut uploaded_filepathes = Vec::new();
let mut website = website.lock().unwrap();
while let Some(item) = payload.next().await {
match item {
Ok(mut field) => {
let up_data = upload_data_from_multipart_field(&field);
if let Err(msg) = up_data {
return HttpResponse::InternalServerError().body(msg);
}
let up_data = up_data.unwrap();
match write_uploaded_file(&website, &mut field, &up_data.filename, up_data.up_type)
.await
{
Err(msg) => return HttpResponse::InternalServerError().body(msg),
Ok(filepath) => uploaded_filepathes.extend(
website
.static_files_manager
.push_path(std::path::Path::new(&filepath)),
),
}
}
Err(e) => {
return HttpResponse::InternalServerError().body(format!("FIELD ERR {:?}", e))
}
}
}
HttpResponse::Ok().json(uploaded_filepathes)
}
#[get("/static-files-index")]
async fn get_static_files_index(website: Data<std::sync::Mutex<WebSite>>) -> impl Responder {
HttpResponse::Ok().json(
website
.lock()
.expect("Couldn't lock website")
.static_files_manager
.get_index(),
)
}
#[delete("/delete-file/{category}/{filename}")]
async fn delete_static_file(
website: Data<std::sync::Mutex<WebSite>>,
fileinfo: Path<(String, String)>,
) -> impl Responder {
let mut website = website.lock().unwrap();
let (cat, fname) = fileinfo.into_inner();
let fpath = std::path::PathBuf::from(cat).join(fname);
match remove_file(website.static_files_manager.dir.join(&fpath)) {
Ok(_) => {
website
.static_files_manager
.remove_path(fpath.to_string_lossy().into());
HttpResponse::Accepted().body("File was deleted")
}
Err(e) => HttpResponse::InternalServerError().body(format!("Error deleting file {:?}", e)),
}
}