2020-09-09
1518
#rust
Mario Zupan
24822
Sep 9, 2020 ⋅ 5 min read

File upload and download in Rust

Mario Zupan I'm a self-employed Software Engineer and Trainer living in Vienna, Austria. I've worked at several companies and in multiple fields building, maintaining and operating distributed systems at scale using Java, Kotlin, Node, Go and Rust. I also taught advanced software engineering courses for several years at the University of Applied Sciences FH Joanneum in Graz and worked as a technical trainer, empowering other software engineers to reach their full potential. Currently, I work as a freelance software engineer and trainer again, looking to help companies build high-quality software solutions. Check out my personal blog: http://www.zupzup.org.

Recent posts:

Building a Full-Featured Laravel Admin Dashboard with Filament

Building a full-featured Laravel admin dashboard with Filament

Build scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.

Kayode Adeniyi
Dec 20, 2024 ⋅ 5 min read
Working With URLs In JavaScript

Working with URLs in JavaScript

Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.

Joe Attardi
Dec 19, 2024 ⋅ 6 min read
Lazy Loading Vs. Eager Loading

Lazy loading vs. Eager loading

In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.

Njong Emy
Dec 18, 2024 ⋅ 5 min read
Deno logo over an orange background

How to migrate your Node.js app to Deno 2.0

Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]

Yashodhan Joshi
Dec 17, 2024 ⋅ 7 min read
View all posts

12 Replies to "File upload and download in Rust"

  1. Thanks for the interesting tutorial. I expanded it slightly by adding cors. This works fine for the download path, but it seems that its not working (even though compiling) for the upload part. The server throws an Internal Server Error about unknown header (“Content-Type”) event thought this is in the cors. Any idea why this could be?

    let download_cors = … (similar to upload cors)

    let upload_cors = warp::cors()
    .allow_any_origin().allow_headers(vec![“User-Agent”, “Sec-Fetch-Mode”, “Referer”, “Origin”, “Access-Control-Request-Method”, “Access-Control-Request-Headers”, “Content-Type”, “Accept”, “Authorization”, “type”])
    .allow_methods(vec![“GET”, “POST”, “DELETE”, “OPTIONS”]);
    let upload_route = warp::path(“upload”).and(warp::post()).and(warp::multipart::form().max_length(5_000_000)).and_then(upload).with(upload_cors);
    let download_route = warp::path(“files”).and(warp::fs::dir(“./files/”)).with(download_cors);

  2. Hey!

    Author here – thanks for the feedback, first and foremost.

    I added your CORS config and for me it works. How are you calling it? I tested it with cURL and Postman and in both cases it worked just fine.

    One thing I sometimes do to debug the errors, is add log statements (printlns for example) on top of the

    async fn handle_rejection(err: Rejection) -> std::result::Result {

    function, to see what rejection is thrown exactly and then I check the warp docs to see why that might happen.

  3. Dear Mario

    Thanks for the reply and sorry for the slow follow up. I figured out what was wrong. I was calling from a react app and the call actually did a pre-flight check using an options request, which of course was not implemented. Thus the call failed.

    Florian

  4. It seems that this example does not go into the details about how to properly structure a file and the functions within.

    I myself care only about the part that claims to show how to send multipart form data to ANY REST API route that is willing to ingest it.

    Code that is implementing upload function seems to raise errors and fail to compile.

    the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try`)
    the trait `Try` is not implemented for `()`
    required by `from_error’

    It is not clear on how to properly use the code that was shown.

  5. Hey Andzej!

    I’m the author of the post. I’m not 100% sure what exact issue you’re encountering.

    In terms of failure to compile – the code in the repository compiles just fine for me. Which version of Rust are you using?

    In terms of structuring the application, you’re right, the goal of this post was not to provide a holistic overview of application structuring, but rather to provide a quick setup for uploading and downloading files using Warp and Rust.

    What’s the exact errors you encounter, or which parts aren’t clear to you? I think it would be best if you opened a ticket at https://github.com/zupzup/warp-upload-download-example with your questions and I’ll be happy to help you!

    kind regards,
    Mario

  6. Hi! Thanks for writing this article!

    I would like to dynamically map the request path to a file path (by querying a database), but it seems to me that warp’s serve dir/fs function cannot be reused for that. How would you implement that?

    Thanks!

  7. Hey!

    So, if I understand you correctly, you’d want to map something like https://example.com/files/some/interesting/file to a file, where you get the actual path of the file via a database query based on the path.

    So somewhere in the DB, there is an entry like “path: /some/interesting/file” => “actualpath: /opt/files/24324.jpg/”.

    In that case, I think you can only do this “manually”, by having a handler on “/files”, which then parses the path, does the query, if it finds anything, read the file (e.g. using tokio::fs) and returns the file to the user with the appropariate HTTP headers.

    I’m not 100% sure I understand you correctly, but it sounds like something you’d have to implement step by step.

    Hope this helps!
    Mario

  8. Hi guys, upload using curl command is working just fine, however, upload from a React app in the Chrome browser gives error 500.
    Application log output was:
    unhandled error: Rejection(InvalidHeader { name: “content-type” })
    Any suggestions ?

  9. Hey

    As the error suggests, I believe the issue is with the “content-type” header. In the CURL command you can see

    –header ‘Content-Type: multipart/form-data’

    So in your React app, please check in the dev tools, if the request sent from your frontend actually contains this header and if not, you can try setting it manually on your upload request.

    Hope this helps!

Leave a Reply