use mime;
use reqwest;
use std::fs;
use std::io::{self, Read};
use std::path::PathBuf;
use uuid::Uuid;
use errors::*;
pub struct Body {
boundary: String,
size: u64,
reader: Box<Read+Send>,
}
impl Body {
pub fn new<S, P>(name: S, path: P) -> Result<Body>
where S: Into<String>, P: Into<PathBuf>
{
let name = name.into();
let path = path.into();
let filename = path.to_string_lossy();
let file = fs::File::open(&path)
.chain_err(|| ErrorKind::CouldNotReadFile(path.clone()))?;
let file_size = file.metadata()?.len();
let boundary = format!("--------------------------{}", Uuid::new_v4());
let header = format!("--{}\r
Content-Disposition: form-data; name=\"{}\"; filename=\"{}\"\r
Content-Type: application/octet-stream\r
\r
", &boundary, &name, filename);
let footer = format!("\r
--{}--\r
", &boundary);
let size = header.len() as u64 + file_size + footer.len() as u64;
let body = io::Cursor::new(header)
.chain(file)
.chain(io::Cursor::new(footer));
Ok(Body {
boundary: boundary,
size: size,
reader: Box::new(body),
})
}
pub fn mime_type(&self) -> mime::Mime {
format!("multipart/form-data; boundary={}", self.boundary)
.parse()
.expect("Could not parse built-in MIME type")
}
}
impl Read for Body {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.reader.read(buf)
}
}
impl From<Body> for reqwest::Body {
fn from(body: Body) -> reqwest::Body {
let size = body.size;
reqwest::Body::sized(body, size)
}
}