I have be googling for hours trying to figure out how to download a PNG image from a java servlet using JAX-RS to a React MUI front end. The Problem is all the examples are for only one side and they don’t talk about how to read/send it from the other side. This is my test code:
Java 17 servlet using Jersey bookmarks:
@GET // get data
@Path("downloadPanoramas") // file/downloadPanoramas is URL
@Produces("image/png") // what format we be use
public Response getPanoramas()
{
Response result;
try
{
// Define a suggested filename
final String fileName = "pano_vis_a_panorama.png";
java.nio.file.Path panoramaPath = get(YamlReader.getImagePath(), fileName);
// Create the JAXRS response
// Don't forget to include the filename in 2 HTTP headers:
//
// a) The standard 'Content-Disposition' one, and
// b) The custom 'X-Suggested-Filename'
//
Response.ResponseBuilder builder = Response.ok(panoramaPath.toFile());
builder.header("Content-Disposition", "attachment; filename=" + fileName);
// All Done.
result = builder.build();
}
catch (RuntimeException ex)
{
JsonObject resultMsg = Json.createObjectBuilder().add("status",
Json.createObjectBuilder().add("code", 1)
.add("message", ex.getMessage())
.build())
.build();
return Response.status(Response.Status.BAD_REQUEST).entity(resultMsg.toString()).build();
}
return result;
}
This is reading in the get request and then sends this image back which I want to display on my web page. I am see most post say to use responseType “arraybuffer” but no one talks about how to do that on the backend. I mimic the the request examples to create the js frontend file, but it can’t read the Response.
React front end
import Typography from "@mui/material/Typography";
import React, {useEffect, useRef, useState} from "react";
import Box from "@mui/material/Box";
import axios from "axios";
import Button from "@mui/material/Button";
const API_ENDPOINT = process.env.REACT_APP_API_ENDPOINT;
const SERVLET_NAME = process.env.REACT_APP_SERVLET_NAME;
function PanoramaTool(props) {
const [image64, setImage64] = useState("");
const url_DP = API_ENDPOINT + "/" + SERVLET_NAME + "/rdt/file/downloadPanoramas"; // Download panorama file request
const getImage = () => {
axios({
method: 'GET',
url: url_DP,
responseType: 'arraybuffer',
}).then((response) => {
setImage64(Buffer.from(response.data, "binary").toString("base64"))
}).catch(function(error) {
console.log(error);
})
};
/**
Create the step layout.
*/
// noinspection JSValidateTypes
return (
<Box sx={{ margin: 2 }}>
<Typography variant="h2" align="center" sx={{mb: 1}} gutterBottom>
Panorama Configuration
</Typography>
<Box>
<Box>
<img src={`data:image/jpeg;charset=utf-8;base64,${image64}`} alt="pano_vis_a_panorama.png"/>
<Button onClick={getImage} sx={{ mt: 1, mr: 1 }}>
panorama
</Button>
</Box>
</Box>
</Box>
);
}
export default PanoramaTool;
When the response read the PanoramaTool, it goes to the catch and fails to read the png file that I want to save in image64 so I can display it.