Search code examples
javascriptreactjsbase64pngarraybuffer

How can I render an ArrayBuffer (PNG image) directly as an image in React?


I'm getting a ArrayBuffer representing a PNG image file sent over a socket. Is there a way to render this directly to an image tab without needing to convert it to base64 first? It seems unnecessary to add the extra conversion step just for rendering.


Solution

  • You can convert array buffer to blob and then use URL.createObjectURL(blob) to create a source to the image.

    Example

    const { useState, useEffect } = React;
    
    const url = "https://cors-anywhere.herokuapp.com/https://www.w3schools.com/howto/img_avatar2.png"
    
    
    const App = () => {
      const [{
        srcBlob,
        srcDataUri
      }, setSrc] = useState({
        srcBlob: null,
        srcDataUri: null
      });
    
      useEffect(() => {
        let isUnmounted = false;
        
        fetch(url, {
        })
          .then(response => response.blob())
          .then(blob => blob.arrayBuffer())
          .then(arrayBuffer => {
    
            if(isUnmounted) {
              return;
            }
            
            const blob = new Blob([arrayBuffer])
            const srcBlob = URL.createObjectURL(blob);
            
            setSrc(state => ({
              ...state,
              srcBlob
            }));
       
          })
        
        return () => {
          isUnmounted = true;
        }
        
      }, [])
    
    return <div>
      {srcBlob && <div>
        <img width="100" height="100" src={srcBlob} alt="image blob"/>
        <div>Blob: {srcBlob}</div>
        </div>}
    </div>
    }
    
    ReactDOM.render(
        <App />,
        document.getElementById('root')
      );
    <script src="https://unpkg.com/react/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <div id="root"></div>