diff --git a/src/requests/form_builder.rs b/src/requests/form_builder.rs
index 72a013e7..6198e403 100644
--- a/src/requests/form_builder.rs
+++ b/src/requests/form_builder.rs
@@ -6,6 +6,7 @@ use crate::{
     requests::utils,
     types::{ChatId, InputMedia, ParseMode},
 };
+use crate::types::InputFile;
 
 /// This is a convenient struct that builds `reqwest::multipart::Form`
 /// from scratch.
@@ -19,28 +20,22 @@ impl FormBuilder {
     }
 
     /// Add the supplied key-value pair to this `FormBuilder`.
-    pub fn add<T>(self, name: &str, value: &T) -> Self
+    pub fn add<T>(self, name: &str, value: T) -> Self
     where
-        T: ToFormValue + ?Sized,
+        T: IntoFormValue,
     {
-        Self {
-            form: self.form.text(name.to_owned(), value.to_form_value()),
+        let name = name.to_owned();
+        match value.into_form_value() {
+            Some(FormValue::Str(string)) => Self {
+                form: self.form.text(name, string),
+            },
+            Some(FormValue::File(path)) => self.add_file(&name, path),
+            None => self,
         }
     }
 
-    /// Adds a key-value pair to the supplied `FormBuilder` if `value` is some.
-    /// Don't forget to implement `serde::Serialize` for `T`!
-    pub fn add_if_some<T>(self, name: &str, value: Option<&T>) -> Self
-    where
-        T: ToFormValue + ?Sized,
-    {
-        match value {
-            None => Self { form: self.form },
-            Some(value) => self.add(name, value),
-        }
-    }
-
-    pub fn add_file(self, name: &str, path_to_file: &PathBuf) -> Self {
+    // used in SendMediaGroup
+    pub fn add_file(self, name: &str, path_to_file: PathBuf) -> Self {
         Self {
             form: self
                 .form
@@ -53,50 +48,83 @@ impl FormBuilder {
     }
 }
 
-pub trait ToFormValue {
-    fn to_form_value(&self) -> String;
+pub enum FormValue {
+    File(PathBuf),
+    Str(String),
+}
+
+pub trait IntoFormValue {
+    fn into_form_value(self) -> Option<FormValue>;
 }
 
 macro_rules! impl_for_struct {
     ($($name:ty),*) => {
         $(
-            impl ToFormValue for $name {
-                fn to_form_value(&self) -> String {
-                    serde_json::to_string(self).expect("serde_json::to_string failed")
+            impl IntoFormValue for $name {
+                fn into_form_value(self) -> Option<FormValue> {
+                    let json = serde_json::to_string(&self)
+                        .expect("serde_json::to_string failed");
+                    Some(FormValue::Str(json))
                 }
             }
         )*
     };
 }
 
-impl_for_struct!(bool, i32, i64, Vec<InputMedia>);
+impl_for_struct!(bool, i32, i64);
 
-impl ToFormValue for str {
-    fn to_form_value(&self) -> String {
-        self.to_owned()
+impl<T> IntoFormValue for Option<T> where T: IntoFormValue {
+    fn into_form_value(self) -> Option<FormValue> {
+        self.and_then(IntoFormValue::into_form_value)
     }
 }
 
-impl ToFormValue for ParseMode {
-    fn to_form_value(&self) -> String {
-        match self {
+impl IntoFormValue for &[InputMedia] {
+    fn into_form_value(self) -> Option<FormValue> {
+        let json = serde_json::to_string(self)
+            .expect("serde_json::to_string failed");
+        Some(FormValue::Str(json))
+    }
+}
+
+impl IntoFormValue for &str {
+    fn into_form_value(self) -> Option<FormValue> {
+        Some(FormValue::Str(self.to_owned()))
+    }
+}
+
+impl IntoFormValue for ParseMode {
+    fn into_form_value(self) -> Option<FormValue> {
+        let string = match self {
             ParseMode::HTML => String::from("HTML"),
             ParseMode::Markdown => String::from("Markdown"),
-        }
+        };
+        Some(FormValue::Str(string))
     }
 }
 
-impl ToFormValue for ChatId {
-    fn to_form_value(&self) -> String {
-        match self {
+impl IntoFormValue for ChatId {
+    fn into_form_value(self) -> Option<FormValue> {
+        let string = match self {
             ChatId::Id(id) => id.to_string(),
             ChatId::ChannelUsername(username) => username.clone(),
-        }
+        };
+        Some(FormValue::Str(string))
     }
 }
 
-impl ToFormValue for String {
-    fn to_form_value(&self) -> String {
-        self.to_owned()
+impl IntoFormValue for String {
+    fn into_form_value(self) -> Option<FormValue> {
+        Some(FormValue::Str(self.to_owned()))
+    }
+}
+
+impl IntoFormValue for InputFile {
+    fn into_form_value(self) -> Option<FormValue> {
+        match self {
+            InputFile::File(path) => Some(FormValue::File(path)),
+            InputFile::Url(url) => Some(FormValue::Str(url)),
+            InputFile::FileId(file_id) => Some(FormValue::Str(file_id)),
+        }
     }
 }
diff --git a/src/requests/send_audio.rs b/src/requests/send_audio.rs
index b41ff0b0..e0e9aca7 100644
--- a/src/requests/send_audio.rs
+++ b/src/requests/send_audio.rs
@@ -74,40 +74,23 @@ impl Request for SendAudio<'_> {
 
 impl SendAudio<'_> {
     pub async fn send(self) -> ResponseResult<Message> {
-        let mut params = FormBuilder::new()
-            .add("chat_id", &self.chat_id)
-            .add_if_some("caption", self.caption.as_ref())
-            .add_if_some("parse_mode", self.parse_mode.as_ref())
-            .add_if_some("duration", self.duration.as_ref())
-            .add_if_some("performer", self.performer.as_ref())
-            .add_if_some("title", self.title.as_ref())
-            .add_if_some(
-                "disable_notification",
-                self.disable_notification.as_ref(),
-            )
-            .add_if_some(
-                "reply_to_message_id",
-                self.reply_to_message_id.as_ref(),
-            );
-        params = match self.audio {
-            InputFile::File(file) => params.add_file("audio", &file),
-            InputFile::Url(url) => params.add("audio", &url),
-            InputFile::FileId(file_id) => params.add("audio", &file_id),
-        };
-        if let Some(thumb) = self.thumb {
-            params = match thumb {
-                InputFile::File(file) => params.add_file("thumb", &file),
-                InputFile::Url(url) => params.add("thumb", &url),
-                InputFile::FileId(file_id) => params.add("thumb", &file_id),
-            }
-        }
-        let params = params.build();
+        let params = FormBuilder::new()
+            .add("chat_id", self.chat_id)
+            .add("caption", self.caption)
+            .add("parse_mode", self.parse_mode)
+            .add("duration", self.duration)
+            .add("performer", self.performer)
+            .add("title", self.title)
+            .add("disable_notification", self.disable_notification)
+            .add("reply_to_message_id", self.reply_to_message_id)
+            .add("audio", self.audio)
+            .add("thumb", self.thumb);
 
         network::request_multipart(
             &self.ctx.client,
             &self.ctx.token,
             "sendAudio",
-            params,
+            params.build(),
         )
         .await
     }
diff --git a/src/requests/send_media_group.rs b/src/requests/send_media_group.rs
index 4e81ab61..3044ca52 100644
--- a/src/requests/send_media_group.rs
+++ b/src/requests/send_media_group.rs
@@ -5,7 +5,7 @@ use crate::{
     requests::{
         form_builder::FormBuilder, Request, RequestContext, ResponseResult,
     },
-    types::{ChatId, InputMedia, Message},
+    types::{ChatId, InputMedia, Message, InputFile},
 };
 
 /// Use this method to send a group of photos or videos as an album.
@@ -32,21 +32,15 @@ impl Request for SendMediaGroup<'_> {
 impl SendMediaGroup<'_> {
     pub async fn send(self) -> ResponseResult<Vec<Message>> {
         let form = FormBuilder::new()
-            .add("chat_id", &self.chat_id)
-            .add("media", &self.media)
-            .add_if_some(
-                "disable_notification",
-                self.disable_notification.as_ref(),
-            )
-            .add_if_some(
-                "reply_to_message_id",
-                self.reply_to_message_id.as_ref(),
-            );
+            .add("chat_id", self.chat_id)
+            .add("media", &self.media[..])
+            .add("disable_notification", self.disable_notification)
+            .add("reply_to_message_id", self.reply_to_message_id);
 
-        let form = self.media.iter().filter_map(|e| e.media().as_file())
-                .fold(form, |acc, path|
+        let form = self.media.into_iter().filter_map(|e| InputFile::from(e).into())
+                .fold(form, |acc, path: std::path::PathBuf|
                     acc.add_file(
-                        &path.file_name().unwrap().to_string_lossy(),
+                        &path.file_name().unwrap().to_string_lossy().into_owned(),
                         path,
                     )
                 );
@@ -96,3 +90,14 @@ impl<'a> SendMediaGroup<'a> {
         self
     }
 }
+
+#[tokio::test]
+async fn main() {
+    use crate::types::InputMedia;
+
+    let bot = crate::bot::Bot::new("457569668:AAF4mhmoPmH1Ud943bZqX-EYRCxKXmTt0f8");
+        bot.send_media_group(218485655, vec![
+            InputMedia::Photo { media: InputFile::File(std::path::PathBuf::from("/home/waffle/Pictures/28b.png")), caption: None, parse_mode: None },
+            InputMedia::Photo { media: InputFile::File(std::path::PathBuf::from("/home/waffle/Pictures/334-3341035_free-png-download-tide-pod-chan-transparent-png.png")), caption: None, parse_mode: None }]).send().await.unwrap();
+    bot.send_photo(218485655, InputFile::File(std::path::PathBuf::from("/home/waffle/Pictures/28b.png"))).send().await.unwrap();
+}
\ No newline at end of file
diff --git a/src/requests/send_photo.rs b/src/requests/send_photo.rs
index 939510b2..33a1daa5 100644
--- a/src/requests/send_photo.rs
+++ b/src/requests/send_photo.rs
@@ -55,31 +55,19 @@ impl Request for SendPhoto<'_> {
 
 impl SendPhoto<'_> {
     pub async fn send(self) -> ResponseResult<Message> {
-        let mut params = FormBuilder::new()
-            .add("chat_id", &self.chat_id)
-            .add_if_some("caption", self.caption.as_ref())
-            .add_if_some("parse_mode", self.parse_mode.as_ref())
-            .add_if_some(
-                "disable_notification",
-                self.disable_notification.as_ref(),
-            )
-            .add_if_some(
-                "reply_to_message_id",
-                self.reply_to_message_id.as_ref(),
-            );
-
-        params = match self.photo {
-            InputFile::File(path) => params.add_file("photo", &path),
-            InputFile::Url(url) => params.add("photo", &url),
-            InputFile::FileId(file_id) => params.add("photo", &file_id),
-        };
-        let params = params.build();
+        let params = FormBuilder::new()
+            .add("chat_id", self.chat_id)
+            .add("caption", self.caption)
+            .add("parse_mode", self.parse_mode)
+            .add("disable_notification", self.disable_notification)
+            .add("reply_to_message_id", self.reply_to_message_id)
+            .add("photo", self.photo);
 
         network::request_multipart(
             &self.ctx.client,
             &self.ctx.token,
             "sendPhoto",
-            params,
+            params.build(),
         )
         .await
     }
diff --git a/src/requests/utils.rs b/src/requests/utils.rs
index 9add97f0..9eecadcf 100644
--- a/src/requests/utils.rs
+++ b/src/requests/utils.rs
@@ -21,8 +21,14 @@ impl tokio::codec::Decoder for FileDecoder {
     }
 }
 
-pub fn file_to_part(path_to_file: &PathBuf) -> Part {
-    let file = tokio::fs::File::open(path_to_file.clone())
+pub fn file_to_part(path_to_file: PathBuf) -> Part {
+    let file_name = path_to_file
+        .file_name()
+        .unwrap()
+        .to_string_lossy()
+        .into_owned();
+
+    let file = tokio::fs::File::open(path_to_file)
         .map(|file| {
             FramedRead::new(
                 file.unwrap(), /* TODO: this can cause panics */
@@ -30,12 +36,6 @@ pub fn file_to_part(path_to_file: &PathBuf) -> Part {
             )
         })
         .flatten_stream();
-    let part = Part::stream(Body::wrap_stream(file)).file_name(
-        path_to_file
-            .file_name()
-            .unwrap()
-            .to_string_lossy()
-            .into_owned(),
-    );
+    let part = Part::stream(Body::wrap_stream(file)).file_name(file_name);
     part
 }
diff --git a/src/types/input_file.rs b/src/types/input_file.rs
index 632e744f..90ac9b08 100644
--- a/src/types/input_file.rs
+++ b/src/types/input_file.rs
@@ -30,6 +30,15 @@ impl InputFile {
     }
 }
 
+impl From<InputFile> for Option<PathBuf> {
+    fn from(file: InputFile) -> Self {
+        match file {
+            InputFile::File(path) => Some(path),
+            _ => None,
+        }
+    }
+}
+
 impl serde::Serialize for InputFile {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
diff --git a/src/types/input_media.rs b/src/types/input_media.rs
index 2fb8fff7..43374167 100644
--- a/src/types/input_media.rs
+++ b/src/types/input_media.rs
@@ -177,6 +177,18 @@ impl InputMedia {
     }
 }
 
+impl From<InputMedia> for InputFile {
+    fn from(media: InputMedia) -> InputFile {
+        match media {
+            InputMedia::Photo { media, .. }
+            | InputMedia::Document { media, .. }
+            | InputMedia::Audio { media, .. }
+            | InputMedia::Animation { media, .. }
+            | InputMedia::Video { media, .. } => media,
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;