Reqwest: send form with bytes

I want to send file to api service like this

extern crate reqwest;
use reqwest::blocking::multipart;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let form = multipart::Form::new()
        .file("file", "test.txt")?;

    let client = reqwest::blocking::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .build()
        .unwrap();
    let res = client.post("https://api.service.com/upload")
        .multipart(form)
        .send()?
        .text()?;
    println!("{}", res);

    Ok(())
}

But use Vec<u8> or &[u8] instead of file method. Can you help me?

Try Form::part with Part::bytes

How to use this?

extern crate reqwest;
use reqwest::blocking::multipart;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let form = multipart::Form::new();

    let value: Vec<u8> = Vec::from("asd");
    let _part = multipart::Part::bytes(value);
    form.part("file", _part);

    let client = reqwest::blocking::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .build()
        .unwrap();
    let res = client
        .post("https://api.service.com/upload")
        .multipart(form)
        .send()?
        .text()?;
    println!("{}", res);

    Ok(())
}

Have error

error[E0382]: use of moved value: `form`
  --> src/main.rs:17:20
   |
5  |     let form = multipart::Form::new();
   |         ---- move occurs because `form` has type `reqwest::blocking::multipart::Form`, which does not implement the `Copy` trait
...
9  |     form.part("file", _part);
   |          ------------------- `form` moved due to this method call
...
17 |         .multipart(form)
   |                    ^^^^ value used here after move
   |
note: this function takes ownership of the receiver `self`, which moves `form`

Most of the methods on Form take self by value, mutate it, and return it[1]

extern crate reqwest;
use reqwest::blocking::multipart;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let form = multipart::Form::new();

    let value: Vec<u8> = Vec::from("asd");
    let _part = multipart::Part::bytes(value);

    let client = reqwest::blocking::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .build()
        .unwrap();
    let res = client
        .post("https://api.service.com/upload")
        .multipart(form.part("file", _part))
        .send()?
        .text()?;
    println!("{}", res);

    Ok(())
}

  1. this is often referred to as the "builder" pattern ↩︎

I understand, that work

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let form = multipart::Form::new();

    let value: Vec<u8> = Vec::from("asd");
    let _part = multipart::Part::bytes(value);
    let _form = form.part("file", _part); // <- this

    let client = reqwest::blocking::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .build()?;
    let res = client
        .post("https://api.service.com/upload")
        .multipart(_form)
        .send()?
        .text()?;
    println!("{}", res);

    Ok(())
}

But I can't understand what wrong...

Clear code

extern crate reqwest;
use reqwest::blocking::multipart;
use std::fs::File;
use std::io::Read;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let filename = "/tmp/send_bytes/Cargo.toml";
    let mut f = File::open(&filename)?;
    let metadata = std::fs::metadata(&filename)?;
    let mut buffer = vec![0; metadata.len() as usize];
    f.read(&mut buffer)?;

    let form = multipart::Form::new();
    let _part = multipart::Part::bytes(buffer);
    let _form = form.part("file", _part);

    let client = reqwest::blocking::Client::builder()
        .redirect(reqwest::redirect::Policy::none())
        .build()?;
    let res = client
        .post("https://api.anonfiles.com/upload")
        .multipart(_form)
        .send()?
        .text()?;
    println!("{}", res);

    Ok(())
}

can't upload file with error
{"status":false,"error":{"message":"No file chosen.","type":"ERROR_FILE_NOT_PROVIDED","code":10}}

this a good form let form = multipart::Form::new().file("file", "/tmp/send_bytes/Cargo.toml")?; with file method.

The server is probably expecting some of the metadata that the file method sets. You should be able to set what it needs manually though.

Part::file_name and Part::mime_str are probably the methods you need to call.

Thank you, multipart::Part::bytes(buffer).file_name() works