rust_wistia/api/upload/
file.rs

1use crate::api::client::UploadClient;
2use crate::models::*;
3use crate::types::Result;
4use crate::RustWistiaError;
5
6use std::fmt::Debug;
7use std::io;
8use std::path::Path;
9
10use hyper::Request;
11use hyper_multipart::client::multipart::Form;
12use hyper_multipart_rfc7578 as hyper_multipart;
13use hyper_multipart_rfc7578::client::multipart::Body;
14
15/// Client implementation to upload *files* and *videos* via the Wistia
16/// **[Upload API]**.
17///
18/// Also check out the [`rust-wistia`] docs for usage and examples.
19///
20/// [`rust-wistia`]: https://docs.rs/rust-wistia
21/// [Upload API]: https://wistia.com/support/developers/upload-api
22///
23#[derive(Clone)]
24pub struct FileUploader<'a, P: AsRef<Path>, B = Body> {
25    client: UploadClient<B>,
26    req: UploadFileRequest<'a, P>,
27}
28
29impl<'a, P: AsRef<Path> + Debug> FileUploader<'a, P> {
30    /// Create a `FileUploader` with a new HTTPS client, with the access token
31    /// retrieved from the environment.
32    ///
33    /// # Arguments
34    ///
35    /// * `file_path` - The path to the media file. The contents of this file
36    /// will be multipart-form encoded into the request body.
37    ///
38    pub fn new(file_path: P) -> Result<Self> {
39        Ok(Self {
40            client: UploadClient::from_env()?,
41            req: UploadFileRequest::new(file_path),
42        })
43    }
44
45    /// Create a `FileUploader` with a new HTTPS client and a Wistia access
46    /// token.
47    ///
48    /// # Arguments
49    ///
50    /// * `file_path` - The path to the media file. The contents of this file
51    /// will be multipart-form encoded into the request body.
52    /// * `access_token` - An API access token used to make requests to the
53    /// Wistia API.
54    ///
55    pub fn with_token(file_path: P, access_token: &str) -> Self {
56        Self {
57            client: UploadClient::from_token(access_token),
58            req: UploadFileRequest::new(file_path),
59        }
60    }
61
62    /// Create a `FileUploader` with a file path and an HTTPS client.
63    ///
64    /// # Arguments
65    ///
66    /// * `file_path` - The path to the media file. The contents of this file
67    /// will be multipart-form encoded into the request body.
68    /// * `client` - The HTTPS client (UploadClient) to use for requests.
69    /// Note that the client must support multipart form requests, via a
70    /// `multipart::Body`.
71    ///
72    pub fn with_client(file_path: P, client: UploadClient<Body>) -> Self {
73        Self {
74            client,
75            req: UploadFileRequest::new(file_path),
76        }
77    }
78
79    /// The hashed id of the project to upload media into. If omitted, a new
80    /// project will be created and uploaded to. The naming convention used
81    /// for such projects is `Uploads_YYYY-MM-DD`.
82    pub fn project_id(mut self, project_id: &'a str) -> Self {
83        self.req.project_id = Some(project_id);
84        self
85    }
86
87    /// A display name to use for the media in Wistia. If omitted, the filename
88    /// will be used instead. This field is limited to 255 characters.
89    pub fn name(mut self, name: &'a str) -> Self {
90        self.req.name = Some(name);
91        self
92    }
93
94    /// A description to use for the media in Wistia. You can use basic HTML
95    /// here, but note that both HTML and CSS will be sanitized.
96    pub fn description(mut self, description: &'a str) -> Self {
97        self.req.description = Some(description);
98        self
99    }
100
101    /// A Wistia contact id, an integer value. If omitted, it will default to
102    /// the contact_id of the account’s owner.
103    pub fn contact_id(mut self, contact_id: &'a str) -> Self {
104        self.req.contact_id = Some(contact_id);
105        self
106    }
107
108    /// Send the Upload File request (with the *multi-part form* data) to the
109    /// Wistia [Upload API].
110    ///
111    /// [Upload API]: https://wistia.com/support/developers/upload-api
112    ///
113    // noinspection DuplicatedCode
114    pub async fn send(&self) -> Result<UploadResponse> {
115        // Build the query parameters to pass to the Upload API
116
117        let params = UploadRequest {
118            access_token: self.client.access_token.as_str(),
119            url: None,
120            project_id: self.req.project_id,
121            name: self.req.name,
122            description: None,
123            contact_id: self.req.contact_id,
124        };
125
126        let url = UploadClient::<Body>::build_url(params)?;
127
128        // Create a request instance and multipart form
129        let req_builder = Request::post(&url);
130        let mut form = Form::default();
131
132        // Add multi-part form fields
133
134        form.add_file("file", &self.req.file_path)
135            .map_err(|e: io::Error| match e.kind() {
136                io::ErrorKind::NotFound => RustWistiaError::FileNotFound(
137                    self.req.file_path.as_ref().to_string_lossy().to_string(),
138                ),
139                _ => RustWistiaError::Io(e),
140            })?;
141
142        if let Some(description) = self.req.description {
143            form.add_text("description", description);
144        }
145
146        // Update a request instance with the multipart Content-Type header
147        // and the payload data.
148        let form = form.set_body::<Body>(req_builder).unwrap();
149
150        // Send the request
151        self.client.make_request(&url, form).await
152    }
153}