A simple file upload server I wrote to learn rust.
-
-
Save bendo01/6666251437df107ecea9ba6e13ae1852 to your computer and use it in GitHub Desktop.
Rust File Upload
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "dataserver" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
actix-multipart = "0.6.0" | |
actix-web = "4.3.1" | |
cargo-watch = "8.4.0" | |
futures-util = "0.3.28" | |
futures = "0.3" | |
image = "0.24.6" | |
mime = "0.3.17" | |
serde = { version = "1.0.164", features = ["derive"] } | |
tokio = { version = "1.29.1", features = ["fs"] } | |
uuid = { version = "1.4.0", features = ["fast-rng", "v4"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fs; | |
use std::io::Write; | |
use std::time::{SystemTime, UNIX_EPOCH}; | |
use futures::StreamExt; | |
use actix_web::{get, post, web, Error, App, HttpResponse, HttpServer, Responder}; | |
use actix_multipart::Multipart; | |
#[get("/")] | |
async fn upload_ui() -> impl Responder { | |
HttpResponse::Ok() | |
.body(r#" | |
<form action="/upload" method="post" enctype="multipart/form-data"> | |
<input type="file" name="file"> | |
<input type="submit"> | |
</form> | |
"#) | |
} | |
#[post("/upload")] | |
async fn upload(req: actix_web::HttpRequest, bytes: web::Payload) -> Result<HttpResponse, Error> { | |
let mut multipart = Multipart::new( | |
req.headers(), | |
bytes | |
); | |
let name_id = r#"test"#; | |
let name_extension = r#"png"#; | |
let name_time = SystemTime::now() | |
.duration_since(UNIX_EPOCH) | |
.expect("Give me your time machine") | |
.as_micros(); | |
let uploaded_name = format!("{}-{:?}.{}", name_id, name_time, name_extension); | |
let mut upload_file = fs::File::create(format!("uploads/{}", uploaded_name))?; | |
while let Some(chunk) = multipart.next().await { | |
let mut chunk = chunk?; | |
while let Some(chunk_content) = chunk.next().await { | |
let content = chunk_content.ok().unwrap_or_default(); | |
upload_file.write(&content)?; | |
} | |
} | |
Ok(HttpResponse::Ok().content_type("text/plain").body(uploaded_name)) | |
} | |
#[actix_web::main] | |
async fn main() -> std::io::Result<()> { | |
fs::create_dir_all("./uploads")?; | |
HttpServer::new(|| { | |
App::new() | |
.service(upload_ui) | |
.service(upload) | |
}) | |
.bind("127.0.0.1:8080")? | |
.run() | |
.await | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment