use crate::api::client::UploadClient;
use crate::constants::DEFAULT_FILENAME;
use crate::https::tls;
use crate::models::*;
use crate::types::Result;
use crate::utils::{stream_reader_from_url, stream_reader_from_url_and_arc_client};
use std::io::{Cursor, Read};
use std::sync::Arc;
use hyper::client::HttpConnector;
use hyper::{body::Bytes, Client, Request};
use hyper_multipart::client::multipart::Form;
use hyper_multipart_rfc7578 as hyper_multipart;
use hyper_multipart_rfc7578::client::multipart::Body;
#[derive(Clone)]
pub struct StreamUploader<'a, R: 'static + Read + Send + Sync, B = Body> {
client: UploadClient<B>,
req: UploadStreamRequest<'a>,
reader: Option<R>,
}
impl<'a> StreamUploader<'a, Cursor<Bytes>> {
pub async fn with_url(url: &str) -> Result<StreamUploader<'a, Cursor<Bytes>>> {
let stream = stream_reader_from_url(url, None).await?;
Self::new(stream)
}
pub async fn with_url_and_token(
url: &str,
access_token: &str,
) -> Result<StreamUploader<'a, Cursor<Bytes>>> {
let stream = stream_reader_from_url(url, None).await?;
Ok(Self::with_token(access_token).stream(stream))
}
pub async fn with_url_and_client(
url: &str,
client: impl Into<Option<Client<tls::HttpsConnector<HttpConnector>>>>,
) -> Result<StreamUploader<'a, Cursor<Bytes>>> {
let stream = stream_reader_from_url(url, client).await?;
Self::new(stream)
}
pub async fn with_url_and_arc_client(
url: &str,
client: Arc<Client<tls::HttpsConnector<HttpConnector>>>,
) -> Result<StreamUploader<'a, Cursor<Bytes>>> {
let stream = stream_reader_from_url_and_arc_client(url, client).await?;
Self::new(stream)
}
}
impl<'a, R: 'static + Read + Send + Sync> StreamUploader<'a, R> {
pub fn new(stream: R) -> Result<Self> {
Self::with_stream_and_filename(stream, DEFAULT_FILENAME)
}
pub fn with_stream_and_filename(stream: R, file_name: &'a str) -> Result<Self> {
Ok(Self {
client: UploadClient::from_env()?,
req: UploadStreamRequest::new(file_name),
reader: Some(stream),
})
}
pub fn with_filename(file_name: &'a str) -> Result<Self> {
Ok(Self {
client: UploadClient::from_env()?,
req: UploadStreamRequest::new(file_name),
reader: None,
})
}
pub fn with_token(access_token: &str) -> Self {
Self {
client: UploadClient::from_token(access_token),
req: UploadStreamRequest::new(DEFAULT_FILENAME),
reader: None,
}
}
pub fn with_client(client: UploadClient<Body>) -> Self {
Self {
client,
req: UploadStreamRequest::new(DEFAULT_FILENAME),
reader: None,
}
}
pub fn stream(mut self, stream: R) -> Self {
self.reader = Some(stream);
self
}
pub fn project_id(mut self, project_id: &'a str) -> Self {
self.req.project_id = Some(project_id);
self
}
pub fn name(mut self, name: &'a str) -> Self {
self.req.name = Some(name);
self
}
pub fn description(mut self, description: &'a str) -> Self {
self.req.description = Some(description);
self
}
pub fn contact_id(mut self, contact_id: &'a str) -> Self {
self.req.contact_id = Some(contact_id);
self
}
pub async fn send(self) -> Result<UploadResponse> {
let params = UploadRequest {
access_token: self.client.access_token.as_str(),
url: None,
project_id: self.req.project_id,
name: self.req.name,
description: None,
contact_id: self.req.contact_id,
};
let url = UploadClient::<Body>::build_url(params)?;
let req_builder = Request::post(&url);
let mut form = Form::default();
form.add_reader_file("file", self.reader.unwrap(), self.req.file_name);
if let Some(description) = self.req.description {
form.add_text("description", description);
}
let form = form.set_body::<Body>(req_builder).unwrap();
self.client.make_request(&url, form).await
}
}