use futures::channel::mpsc::Sender;
use futures::{SinkExt, StreamExt};
use reqwest::{Client, Response};
use super::image_data::ImageData;
use crate::error::ImageDownloadError;
use crate::util::Util;
#[derive(Debug)]
pub struct ImageRequest {
url: String,
response: Response,
content_length: usize,
content_type: String,
}
impl ImageRequest {
pub async fn new(url: String, client: &Client) -> Result<Self, ImageDownloadError> {
let response = client.get(&url).send().await?;
let content_type = Util::get_content_type(&response)?;
let content_length = Util::get_content_length(&response)?;
if !content_type.contains("image") {
return Err(ImageDownloadError::ContentType);
}
Ok(Self {
url,
response,
content_length,
content_type,
})
}
pub async fn download(self, tx: &mut Sender<usize>) -> Result<ImageData, ImageDownloadError> {
let mut stream = self.response.bytes_stream();
let mut result = Vec::with_capacity(self.content_length);
while let Some(item) = stream.next().await {
let chunk = item?;
_ = tx.send(chunk.len()).await;
for byte in chunk {
result.push(byte);
}
}
Ok(ImageData {
url: self.url,
data: result,
content_type: self.content_type,
})
}
pub fn content_type(&self) -> &str {
&self.content_type
}
pub fn content_length(&self) -> usize {
self.content_length
}
}