Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
Commit 16b70c57 authored by Pierre Jarriges's avatar Pierre Jarriges
Browse files

wip upload ans create file

parent 27ef0dae
No related branches found
No related tags found
1 merge request!9Upload files
......@@ -101,7 +101,7 @@ dependencies = [
"http",
"httparse",
"indexmap",
"itoa",
"itoa 0.4.8",
"language-tags",
"lazy_static",
"log",
......@@ -128,6 +128,24 @@ dependencies = [
"syn",
]
[[package]]
name = "actix-multipart"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "774bfeb11b54bf9c857a005b8ab893293da4eaff79261a66a9200dab7f5ab6e3"
dependencies = [
"actix-service",
"actix-utils",
"actix-web",
"bytes 0.5.6",
"derive_more",
"futures-util",
"httparse",
"log",
"mime",
"twoway",
]
[[package]]
name = "actix-router"
version = "0.2.7"
......@@ -1111,13 +1129,13 @@ dependencies = [
[[package]]
name = "http"
version = "0.2.4"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11"
checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
dependencies = [
"bytes 1.1.0",
"fnv",
"itoa",
"itoa 1.0.2",
]
[[package]]
......@@ -1163,7 +1181,7 @@ dependencies = [
"http-body",
"httparse",
"httpdate",
"itoa",
"itoa 0.4.8",
"pin-project 1.0.8",
"socket2",
"tokio",
......@@ -1257,6 +1275,12 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
name = "js-sys"
version = "0.3.55"
......@@ -1281,6 +1305,7 @@ name = "kuadrado_server"
version = "2.0.2"
dependencies = [
"actix-files",
"actix-multipart",
"actix-web",
"actix-web-middleware-redirect-https",
"chrono",
......@@ -1313,9 +1338,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.102"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "linked-hash-map"
......@@ -1325,9 +1350,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "lock_api"
version = "0.4.5"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
......@@ -1588,9 +1613,9 @@ checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170"
[[package]]
name = "once_cell"
version = "1.8.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "opaque-debug"
......@@ -2107,7 +2132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
dependencies = [
"indexmap",
"itoa",
"itoa 0.4.8",
"ryu",
"serde",
]
......@@ -2119,7 +2144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
dependencies = [
"form_urlencoded",
"itoa",
"itoa 0.4.8",
"ryu",
"serde",
]
......@@ -2537,9 +2562,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.28"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
dependencies = [
"cfg-if 1.0.0",
"log",
......@@ -2549,11 +2574,11 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.20"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf"
checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
dependencies = [
"lazy_static",
"once_cell",
]
[[package]]
......@@ -2612,6 +2637,16 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "twoway"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47"
dependencies = [
"memchr",
"unchecked-index",
]
[[package]]
name = "typed-builder"
version = "0.4.1"
......@@ -2635,6 +2670,12 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unchecked-index"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
[[package]]
name = "unicase"
version = "2.6.0"
......
......@@ -25,3 +25,4 @@ time = "0.2.7"
regex = "1.5"
tokio = { version = "0.2", features = ["full"] }
sitemap = "0.4.1"
actix-multipart = "0.3"
const { fetch_post_file } = require("../xhr");
const CreateArticleForm = require("./create-article-form");
const UpdateArticleForm = require("./update-article-form");
......@@ -30,6 +31,19 @@ class RootComponent {
tag: "main",
contents: [
{ tag: "h1", contents: "Kuadrado admin panel" },
{
tag: "form",
style_rules: { border: "1px solid black" },
enctype: "multipart/form-data",
onsubmit: function (e) {
e.preventDefault();
fetch_post_file(e.target).then(res => console.log(res)).catch(err => console.log(err));
},
contents: [
{ tag: "input", name: "file", type: "file" },
{ tag: "input", type: "submit" }
]
},
{
tag: "nav",
contents: [
......
......@@ -104,6 +104,23 @@ function fetch_all_articles() {
});
}
function fetch_post_file(form) {
return new Promise((resolve, reject) => {
fetch("/post-file", {
method: "POST",
body: new FormData(form),
}).then(async res => {
const res_text = await res.text();
if (res.status >= 400 && res.status < 600) {
reject(res_text)
} else {
resolve(res_text);
}
})
})
}
module.exports = {
fetch_article,
......@@ -112,4 +129,5 @@ module.exports = {
fetch_update_article,
fetch_delete_article,
fetch_all_articles,
fetch_post_file,
}
\ No newline at end of file
......@@ -87,6 +87,7 @@ async fn main() -> std::io::Result<()> {
.service(get_articles_by_category)
.service(get_article)
.service(get_all_articles)
.service(post_file)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// STANDARD FILES ///////////////////////////////////////////////////////////////////////////////////////////
.service(resource("/favicon.ico").route(get().to(favicon)))
......
mod admin_auth;
mod articles;
mod static_files;
pub use admin_auth::*;
pub use articles::*;
pub use static_files::*;
use crate::{middleware::AuthenticatedAdminMiddleware, AppState};
use actix_multipart::Multipart;
use actix_web::{
post,
web::{block, Data},
HttpRequest, HttpResponse, Responder,
};
use futures::StreamExt;
use std::{
fs::{remove_file, File},
io::Write,
path::Path,
sync::Arc,
};
#[post("/post-file")]
pub async fn post_file(
app_state: Data<AppState>,
mut payload: Multipart,
middleware: Data<AuthenticatedAdminMiddleware<'_>>,
req: HttpRequest,
) -> impl Responder {
if middleware.exec(&app_state, &req, None).await.is_err() {
return HttpResponse::Unauthorized().finish();
}
while let Some(item) = payload.next().await {
match item {
Ok(mut field) => {
// Field in turn is stream of *Bytes* object
// A multipart/form-data stream has to contain `content_disposition`
let content_disposition = field
.content_disposition()
.expect("Missing Content Disposition header");
let filename = content_disposition.get_filename().expect("Missin filename");
let filepath = Arc::new(Path::new(format!("./tmp/{filename}")));
// File::create is blocking operation, use threadpool
let mut f = block(|| File::create(*filepath.clone())).await;
if f.is_err() {
return HttpResponse::InternalServerError()
.body(format!("Error creating file {:?}", f));
}
let f = f.unwrap();
let mut error = None;
// Field in turn is stream of *Bytes* object
'chunks: while let Some(chunk) = field.next().await {
match chunk {
Ok(chunk) => {
// filesystem operations are blocking, we have to use threadpool
if block(move || f.write_all(&chunk).map(|_| f)).await.is_err() {
error = Some("Error writing chunk".to_string());
break 'chunks;
}
}
Err(e) => {
error = format!("Error writing file {} : {:?}", filename, e);
break 'chunks;
}
}
}
if let Some(err) = error {
block(|| remove_file(*filepath.clone())).await.unwrap();
return HttpResponse::InternalServerError().body(err);
}
}
Err(e) => {
return HttpResponse::InternalServerError().body(format!("FIELD ERR {:?}", e))
}
}
}
HttpResponse::Ok().body("File was successfully uploaded")
}
// use futures::TryStreamExt;
// use std::io::Write;
// pub async fn save_file(mut payload: Multipart) -> impl Responder {
// println!("SAVE FILE");
// // iterate over multipart stream
// while let Some(mut field) = payload.try_next().await.unwrap() {
// // A multipart/form-data stream has to contain `content_disposition`
// let content_disposition = field.content_disposition().unwrap();
// let filename = content_disposition.get_filename().unwrap();
// let filepath = format!("./tmp/{filename}");
// // File::create is blocking operation, use threadpool
// let mut f = actix_web::web::block(|| std::fs::File::create(filepath))
// .await
// .unwrap();
// // Field in turn is stream of *Bytes* object
// while let Some(chunk) = field.try_next().await.unwrap() {
// // filesystem operations are blocking, we have to use threadpool
// f = actix_web::web::block(move || f.write_all(&chunk).map(|_| f))
// .await
// .unwrap();
// }
// }
// HttpResponse::Ok().body("sucess")
// }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment