Reputation: 10395
I am trying to generate an image and then send it in a response from actix_web, I implemented a Trace trait in which I attempted to pass the image bytes to actix_web::web::Bytes, but my attempts fail to compile because my generated image data/bytes is not static.
example code below:
pub struct Image {
pub index: usize,
pub bytes_in_a_chunk: usize,
pub raw: Vec<u8>,
}
impl futures::stream::Stream for Image {
type Item = Result<actix_web::web::Bytes, actix_web::Error>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let length = self.raw.len();
let bytes = self.raw.clone();
let beg = self.index;
let mut end = self.index + self.bytes;
if end >= length {
end = end - length;
}
let data = &bytes[beg..end];
self.index += self.bytes_in_a_chunk;
if data.len() <= 0 {
Poll::Ready(None)
} else {
Poll::Ready(Some(Ok(actix_web::web::Bytes::from(data))))
}
}
}
pub async fn get_image() -> HttpResponse {
let image: Image = generate_image();
HttpResponse::PartialContent()
.content_type(PNG_CONTENT_TYPE)
.streaming(image);
}
Is there a way to stream dynamically generated bytes in a response? I assume there must be a way but I'm having a hard time finding examples or documentation that doesn't involve sending a static string.
Thanks for any help! Cheers!
Upvotes: 1
Views: 1723
Reputation: 60517
Are you sure you need a stream? A stream is basically an asynchronous iterator, but if you have the full image already in memory it shouldn't be necessary.
You can copy the bytes using Body::from_slice
:
pub async fn get_image() -> HttpResponse {
let image: Image = generate_image();
HttpResponse::Ok()
.content_type("image/png")
.body(Body::from_slice(&image.raw))
}
Or transfer ownership of the bytes directly:
pub async fn get_image() -> HttpResponse {
let Image { raw, .. } = generate_image();
HttpResponse::Ok()
.content_type("image/png")
.body(raw)
}
Upvotes: 3