Как мне передавать нестатические байты в http-ответе в actix_web / rust?

#dynamic #rust #streaming #httpresponse #actix-web

#динамический #Ржавчина #потоковая передача #httpresponse #actix-web

Вопрос:

Я пытаюсь сгенерировать изображение, а затем отправить его в ответе от actix_web, я реализовал трассировку, в которой я пытался передать байты изображения в actix_web ::web::Bytes, но мои попытки не завершаются компиляцией, потому что мои сгенерированные данные / байты изображения не являются статическими.

пример кода ниже:

 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<amp;mut Self>, _cx: amp;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 = amp;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);
}
 

Есть ли способ передавать динамически генерируемые байты в ответе? Я предполагаю, что должен быть способ, но мне трудно найти примеры или документацию, которые не включают отправку статической строки.

Спасибо за любую помощь! Приветствия!

Комментарии:

1. Похоже Bytes::copy_from_slice , это может сделать то, что вы хотите.

2. Bytes::copy_from_slice сделал свое дело, спасибо!

Ответ №1:

Вы уверены, что вам нужен поток? Поток — это, по сути, асинхронный итератор, но если у вас уже есть полное изображение в памяти, в этом не должно быть необходимости.

Вы можете скопировать байты с помощью Body::from_slice :

 pub async fn get_image() -> HttpResponse {
    let image: Image = generate_image();
    HttpResponse::Ok()
      .content_type("image/png")
      .body(Body::from_slice(amp;image.raw))
}
 

Или передать право собственности на байты напрямую:

 pub async fn get_image() -> HttpResponse {
    let Image { raw, .. } = generate_image();
    HttpResponse::Ok()
      .content_type("image/png")
      .body(raw)
}