I am using reqwest crate to post a file to https://temp.sh/ but every time getting Upload failed: 404 Not Found.
Here is what I have done:
use futures::stream::TryStreamExt;
use reqwest::{Body, Client};
use std::{fs, path::PathBuf};
use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = rfd::FileDialog::new()
.set_title("Select the file")
.pick_file();
let file: PathBuf = match file {
Some(f) => f,
None => {
eprintln!("❌ No file selected.");
return Ok(());
}
};
let data = fs::read(&file)?; // read entire file into memory
let filename = file.file_name().unwrap().to_string_lossy().to_string();
let url = format!("https://temp.sh/{}", filename);
let client = Client::new();
let res = client
.put(&url) // temp.sh requires PUT
.body(data)
.send()
.await?;
if res.status().is_success() {
println!("✅ Uploaded");
} else {
eprintln!("❌ Upload failed: {}", res.status());
}
Ok(())
}
Corresponding curl command is curl -F "file=@test.txt" https://temp.sh/upload
What am i doing wrong?
This puts file foo.bar to temp.sh/foo.bar instead of temp.sh/upload.
what is the recommended workaround?
can i add upload to the url for it to work?
Not a workaround, but a fix - make request to the correct URL, that is, to "https://temp.sh/upload".
Getting Error 404:Not Found.
keyosk
September 4, 2025, 5:37pm
6
The example curl from their website specifies POST, not PUT. In addition to fixing the URL, you'll need to fix the request method.
let url = format!("https://temp.sh/upload/{}", filename);
let client = Client::new();
let res = client
.post(&url)
.body(data)
.send()
.await?;
I changed it to post.
keyosk
September 4, 2025, 5:39pm
8
The URL is still wrong. It should stop at /upload and not contain a filename. Please review the example curl from the website once more, and verify you can upload a file using their curl example.
curl is working.
But the output of the code:
Error: reqwest::Error { kind: Request, url: "https://temp.sh/upload", source: hyper_util::client::legacy::Error(Connect, ConnectError("tcp connect error", 51.91.79.17:443, Os { code: 101, kind: NetworkUnreachable, message: "Network is unreachable" })) }
kpreid
September 4, 2025, 6:58pm
11
The Rust Playground does not allow any network access at all — if it did, it would surely be abused for spam and attacks. (That said, I don't see the playground being mentioned previously in this thread?)
Yeah not using playground.
Notice that the cURL example is using the -F flag, which will send a POST request using multipart/form-data.
Here's an example of doing something similar with Reqwest:
let file = tokio::fs::read(your_file_path).await.unwrap();
//make form part of file
let file_part_bytes = multipart::Part::bytes(file.clone())
.file_name("your_file_name.txt")
.mime_str("application/octet-stream")
.unwrap();
let client = Client::new();
let response = client
.post("https://temp.sh/upload")
.multipart(
multipart::Form::new()
.part("file", file_part_bytes)
)
.send()
.await
.unwrap();
1 Like
Schard
September 4, 2025, 9:08pm
15
This worked for me:
use clap::Parser;
use reqwest::Client;
use reqwest::multipart::Form;
use std::path::PathBuf;
const URL: &str = "https://temp.sh/upload";
#[derive(Debug, Parser)]
struct Args {
file: PathBuf,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
let form = Form::new().file("file", args.file).await?;
let url = Client::new()
.post(URL)
.multipart(form)
.send()
.await?
.error_for_status()?
.text()
.await?;
println!("{url}");
Ok(())
}
~/tempshclt> cargo run -- Cargo.toml
Compiling tempshclt v0.1.0 (/home/neumann/tempshclt)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 19.20s
Running `target/debug/tempshclt Cargo.toml`
http://temp.sh/ittdk/Cargo.toml
~/tempshclt>
2 Likes
Nice! I just copied my example from one of my tests that sends a multipart request with two parts: bytes and json.
That added some overhead, so your example is simpler and better for the O.P. .
system
Closed
December 4, 2025, 1:44pm
18
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.