I tried to send a PNG as GET
-response to a client with axum. For this I load an image into a DynamicImage
from the image crate. When I send a request from my browser, no image is shown. In firefox I get the message:
The image "http://<the-URL-of-the-GET-request>" cannot be displayed because it contains errors.
In my terminal is no error message.
The reason I put the image in an DynamicImage
object in my example is because I want to generate images on request and then reply to the client.
First, I created an API, where I can get the image following the instructions in the axum documentation.
let app = Router::new().route("/image", get(get_image)).with_state(());
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
The function get_image()
loads the PNG-file, put it in an DynamicImage
from the image crate. Next, I try to send the bytes back to the client.
pub async fn get_image() -> impl axum::response::IntoResponse {
let img_path = PathBuf::from("<path/to/image>").join("ferris.png");
let image = image::io::Reader::open(&img_path).unwrap().decode().unwrap();
(
axum::response::AppendHeaders([(header::CONTENT_TYPE, "image/png")]),
image.into_bytes()
)
}
For this, I adapted the code from here. But I tried to load the image from hard drive and not, as in the example shown, from base64 string.
I also converted the image to a base64 string and sent this back as shown in the example. This worked fine. However, I don't want to convert the image into a string every time, only to be able to send it again as a byte stream. Is there any direct way that I am overlooking?
Instead of converting the raw bitmap (your DynamicImage
) into bytes, you must encode it to adhere to the PNG format.
Something like this should work to convert the raw image to PNG and write the PNG to a a byte buffer that you can serve with axum:
use image::ImageFormat;
use std::io::{BufWriter, Cursor};
let mut buffer = BufWriter::new(Cursor::new(Vec::new()));
image.write_to(&mut buffer, ImageFormat::Png).unwrap();
let bytes: Vec<u8> = buffer.into_inner().unwrap().into_inner();