1use std::path::Path;
2
3use futures_util::TryFutureExt;
4use mime::Mime;
5use reqwest::multipart::Part;
6use reqwest::Body;
7use tokio::fs::File;
8use tokio::io::AsyncRead;
9use tokio_util::io::ReaderStream;
10
11pub struct FileSource {
12 pub body: Body,
13 pub filename: String,
14 pub mime: Mime,
15}
16
17impl FileSource {
18 pub fn new_from_file<P: AsRef<Path>>(file: P, filename: String, mime: Mime) -> Self {
19 let file = file.as_ref().to_path_buf();
20 let st = File::open(file)
21 .map_ok(ReaderStream::new)
22 .try_flatten_stream();
23
24 FileSource {
25 body: Body::wrap_stream(st),
26 filename,
27 mime,
28 }
29 }
30
31 pub fn new_from_read<T>(read: T, filename: String, mime: Mime) -> Self
32 where
33 T: AsyncRead + Send + Sync + Unpin + 'static,
34 {
35 FileSource {
36 body: Body::wrap_stream(ReaderStream::new(read)),
37 filename,
38 mime,
39 }
40 }
41}
42
43impl From<FileSource> for Part {
44 fn from(source: FileSource) -> Part {
45 Part::stream(source.body)
46 .file_name(source.filename)
47 .mime_str(source.mime.as_ref())
48 .expect("FileSource::into::<Part>()")
49 }
50}