I am looking for a workaround to authenticate image requests in a RESTful app, see JWT-based authentication for tags?. I’ve come to a solution which uses Axios
to grab the images via api routes (where the auth layer is already set).
I’ve tested two ways to grab a binary resource via axios
, one is using a blob
the second an arraybuffer
, they both seemed to work fine:
Blob / FileReader, ReadAsDataUrl
:
const SecuredImageAsBlob = ({ path, ...props }: Props) => {
const [imageDataUrl, setImageDataUrl] = useState<string | ArrayBuffer | null>()
useEffect(() => {
axiosWithAuthHeaders
.get(`/securedimage/${path}`, {
responseType: "blob",
})
.then(response => {
var reader = new window.FileReader()
reader.readAsDataURL(response.data)
reader.onload = function () {
setImageDataUrl(reader.result)
}
})
return () => {}
}, [path])
return imageDataUrl ? <img src={String(imageDataUrl)} {...props} /> : null
}
vs Buffer / toString("base64")
:
const SecuredImageAsBuffer = ({ path, ...props }: Props) => {
const [base64string, setBase64string] = useState<string | null>()
useEffect(() => {
axiosWithAuthHeaders
.get(`/securedimage/${path}`, {
responseType: "arraybuffer",
})
.then(response => {
const buffer = Buffer.from(response.data, "binary").toString("base64")
setBase64string(buffer)
})
return () => {}
}, [path])
return base64string ? <img src={`data:image/png;base64,${base64string}`} {...props} /> : null
}
But which one is more performant? I would say the Blob
with FileReader()
and readAsDataUrl
, because it is reading a stream, so it can start to paint the image before it is fully loaded (which is close to the native <img />
behaviour). Buffer, on the other hand, has to be fully loaded and then converted to base64 before it can be shown as image, and I also guess it would take more memory because the size would be bigger. But I might be completely wrong, so feel free to correct me!
What do you thing? Blob / FileReader
, Buffer / base64
, or some other way I completely missed?