1

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!

2
  • It looks like Bytes::copy_from_slice might do what you want. Commented Feb 26, 2021 at 23:21
  • Bytes::copy_from_slice did the trick, thank you! Commented Feb 27, 2021 at 0:25

1 Answer 1

3

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)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.