use mime;
use std::fs;
use std::io::{self, Read};
use std::path::PathBuf;
use uuid::Uuid;
use errors::*;
pub struct Body {
boundary: String,
reader: Box<Read>,
}
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 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 body = io::Cursor::new(header)
.chain(file)
.chain(io::Cursor::new(footer));
Ok(Body {
boundary: boundary,
reader: Box::new(body)
})
}
pub fn mime_type(&self) -> mime::Mime {
mime::Mime(mime::TopLevel::Multipart,
mime::SubLevel::FormData,
vec![(mime::Attr::Boundary,
mime::Value::Ext(self.boundary.to_owned()))])
}
}
impl Read for Body {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.reader.read(buf)
}
}