A simple file upload server I wrote to learn rust.
Created
July 14, 2021 12:39
-
-
Save uint0/43a821ee59271328361239293aea1be2 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 = "file-receiver" | |
version = "0.1.0" | |
authors = ["uint0 <uint0@zeta-mechanic>"] | |
edition = "2018" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
actix-web = "3" | |
actix-multipart="0.3" | |
futures = "0.3" | |
human_id = "0.1" |
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 human_id; | |
use actix_web::{get, post, web, Error, App, HttpResponse, HttpServer, Responder}; | |
use actix_multipart::Multipart; | |
#[get("/")] | |
async fn upload_ui() -> impl Responder { | |
HttpResponse::Ok() | |
.header("Content-Type", "text/html") | |
.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: web::HttpRequest, bytes: web::Payload) -> Result<HttpResponse, Error> { | |
let mut multipart = Multipart::new( | |
req.headers(), | |
bytes | |
); | |
let name_id = human_id::id("", true); | |
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); | |
let mut upload_file = fs::File::create(format!("uploads/{}", uploaded_name))?; | |
while let Some(chunk) = multipart.next().await { | |
let mut chunk = chunk?; | |
for chunk_content in 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