5

I want to load an image from server that requires a token, but I don't know how to send the token in headers of axios or fetch request to get it loaded. How can I send headers with url to load my image from server in my React application?

Here is my image tag

<img 
   src={{
    uri: `${activeCoverHash}`,
    headers: { t: token }
   }} 
   alt={i.name}
   onLoad={() => console.log('___DONE___')}/>

but it gives me a 404 error. What can I do?

Actually I got that pattern from here, but it is only works on React Native not React.

halfer
  • 19,824
  • 17
  • 99
  • 186
amdev
  • 6,703
  • 6
  • 42
  • 64

3 Answers3

10

You can load the image by fetching the image using javascript and then loading it in the src attribute of image tag.

componentDidMount() {
    axios.get(`${activeCoverHash}`, { headers: {'t': token }, responseType: 'arraybuffer'}).then((res) => {

      let data = new Uint8Array(res.data);
      let raw = String.fromCharCode.apply(null, data);
      let base64 = btoa(raw);
      let src = "data:image;base64," + base64;

      this.img.src = src;
    });
  }

render() {
    return (
        <img src={""} alt={"Loading..."} ref={(e) => this.img = e} />
    )
}
Prakash Sharma
  • 15,542
  • 6
  • 30
  • 37
  • can you please present a non async await example , please ,please please , i need to check some thing ... thank you – amdev Oct 21 '18 at 14:00
  • im getting this error: Uncaught (in promise) TypeError: Cannot add property src, object is not extensible, it seems that its working , but has a little problem here , please help man , i appropriate you – amdev Oct 21 '18 at 14:12
  • the ref solution does not worked but i made it work by saving it in the state and calling it in render , is it good to store large data in state ??? – amdev Oct 21 '18 at 14:31
  • That should not be a big problem. Though i wonder why ref is not working – Prakash Sharma Oct 21 '18 at 14:43
2

Using IONIC v4 and React would be:

import React from 'react';
import API from '../api';

type ImageWithAuthProps = {
    url: string;
}

const ImageWithAuth: React.FC<ImageWithAuthProps> = (props) => {

    // Components refs
    const img: React.Ref<HTMLImageElement> = React.createRef();

    // Load data
    React.useEffect(() => {
        API.get(`${props.url}`,
        {
            responseType: 'arraybuffer',
            headers: {
                'Accept': 'image/jpeg'
            }
        }).then((res) => {

            const blob = new Blob([res.data], {
                type: 'image/jpeg',
            });

            console.log("blob: ", blob);
            var objectURL = URL.createObjectURL(blob);
            if (img.current != null)
                img.current!.src = objectURL;
        });
    }, []);

    return (
        <img src={""} alt={"Loading..."} ref={img} />
    );

};

export default ImageWithAuth;
Mariusz Wiazowski
  • 2,118
  • 1
  • 16
  • 17
  • Thanks for providing this alternative solution which however has no relation with Ionic. It will work with any React web app. – Lars Blumberg Nov 20 '20 at 09:56
0

I applied the react solution from @MariuszWiazowski, it works without Ionic however when using <ImageWithAuth/> component in several places in my app I noticed it sometimes displays image alt instead of image itself.

It seems the problem occurs when image is already fetched but img.current is still null. To avoid it we should save fetched image to component state using useState and update img.current.src only after we have fetchedImage and img ref is not null.

Something like this:

export const ImageWithAuth: React.FC<ImageWithAuthProps> = ({ url }) => {

  const [fetchedImage, setFetchedImage] = useState<string | undefined>()
  const img: React.Ref<HTMLImageElement> = React.createRef()

  useEffect(() => {
    axios
      .get(`${url}`, {
        responseType: 'arraybuffer',
        headers: {
          Accept: 'image/jpeg',
        },
      })
      .then((res) => {
        const blob = new Blob([res.data], {
          type: 'image/jpeg',
        })

        const objectURL = URL.createObjectURL(blob)
        setFetchedImage(objectURL)
      })
  }, [url])


  useEffect(() => {
  // Make sure img.current is not null and image is fetched
    if (img.current && fetchedImage) {
      img.current.src = fetchedImage
    }
  }, [fetchedImage])

  return <img src={''} alt={'Loading...'} ref={img} />
}

export default ImageWithAuth
Pawel
  • 78
  • 9