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}