🏠Home📚Blogs
📝Post

Simple file sharing server in Rust for beginners

a day ago | 📖 5 min read


Have you ever wanted to quickly share a file across devices on your local network? Maybe you're tinkering with a Raspberry Pi, or maybe you just want a no-fuss way to transfer a file from your desktop to your phone. In this post, we'll build a simple file sharing server in Rust, step-by-step. If you’re new to Rust or backend stuff, don’t worry—I’ll explain everything like we’re chatting over coffee ☕


What Are We Building?

We're making a tiny file-sharing server that:

  • Lets users upload files via curl
  • Stores them on the server.
  • Gives you a downloadable URL in return.
  • Serves files when the link is accessed.

All this in under 200 lines of Rust code!

If you would like to directly jump over to code teabox-server is the repository you are looking for.


Getting Started

Make sure you have Rust installed and then clone the repo:

git clone https://github.com/Binabh/teabox-server cd teabox-server cargo run

By default, it runs on http://127.0.0.1:7878.

Try uploading a file with command below —it’ll return a URL you can use to download the file again.

curl -F 'file=@yourfile' 127.0.0.1:7878

Neat, right?


Let's Break Down the Code

We’ll look at the code in chunks, and I’ll explain what each part does.

1. Setup and Listening for Connections

let addr = env::args() .nth(1) .unwrap_or_else(|| LOCAL_ADDRESS.to_string()); let listener = TcpListener::bind(&addr).await.unwrap();

Here, the server reads the desired address from the command line or falls back to 127.0.0.1:7878. Then it binds a TCP listener to that address—basically saying, “Hey OS, I’m ready to accept connections here.”


2. Handling HTTP Requests

Each incoming request is passed to a function called respond:

Http::new() .serve_connection(stream, service_fn(respond)) .await

The respond function handles:

  • GET / – shows simple html.
  • POST / – processes file uploads.
  • GET /<filename> – serves uploaded files.
  • Everything else → custom 404 page.

3. The Upload Page (GET /)

let file_path = PathBuf::from(TEMPLATE_FOLDER).join("index.html"); let body = fs::read_to_string(file_path).await.unwrap();

It just loads and serves an index.html page that just has a basic greeting message for now however it can be extended with simple html file upload form. This page lives in a templates/ folder.


4. Handling File Uploads (POST /)

When a file is submitted, we parse it as multipart/form-data, the standard way curl/browsers send files:

let boundary = req.headers() .get(CONTENT_TYPE) .and_then(|ct| ct.to_str().ok()) .and_then(|ct| multer::parse_boundary(ct).ok());

Using multer, we loop through all uploaded fields, and for each file, we:

  • Read the bytes.
  • Guess its type using infer.
  • Generate a short hash-based name (so URLs are clean and unique).
  • Save it to the uploads/ folder.
let filename = encoded[..6].to_owned() + "." + kind.extension();

Then we return the download link!


5. Serving Files (GET /filename)

When you visit the returned link, it looks something like:

http://127.0.0.1:7878/a1b2c3.png

The server checks the uploads/ folder for this file and sends it back.

If the file doesn’t exist, it shows a custom 404 page from templates/404.html.


Bonus: File Type Detection and Hashing

let kind = match infer::get(&data) { Some(kind) => kind, None => infer::Type::new(infer::MatcherType::Text, "text", "txt", custom_matcher), };

This ensures even unknown file types default to .txt, so nothing breaks.

And hashing the file content helps generate unique names:

let hash = Sha256::digest(&data);

Then we Base64-encode the hash and use the first 6 characters as a filename.

Customizing It

Want to tweak it for yourself? Here are some ideas:

  • Add password protection for uploads.
  • Make the server accessible from your LAN.
  • Limit upload file size.
  • Automatically clean up old files.
  • Host this in a VPS behind a reverse proxy like nginx.

Everything is plain and open—you can customize it however you like!


Conclusion

You now have a working file sharing server built with Rust 🎉

It’s simple, fast, and great for local network use. You’ve seen how to handle HTTP requests, parse file uploads, serve static files, and organize your server code cleanly.

Want to go deeper? Explore the codebase here: 👉 GitHub Repo: Binabh/teabox-server

Let me know if you build something cool with it—or if you have questions, feel free to open an issue or reach out. Happy hacking!


Share this on

Related Blogs;