2

I created an ImageUrl using the following code in React with Typescript. It made a URL, however does not show a picture image. Clicking on the URL eg "http://localhost:3003/0b4de100-d8eb-49a7-b43a-e2147310abbe" gives error below. How can I fix this ?

Error:

http://localhost:3003/0b4de100-d8eb-49a7-b43a-e2147310abbe Failed to load resource: the server responded with a status of 404 (Not Found)

Code:

 const [photoURL, setPhotoUrl] = useState<string>('');

 const pictureData = await getPatientAvatar(patientId);
 const blob = new Blob([pictureData], { type: 'image/jpeg' });
 const imageUrl = URL.createObjectURL(blob);
 setPhotoUrl(imageUrl);

 <img src={photoUrl} />

Picture in Network Tab:

enter image description here

mattsmith5
  • 540
  • 4
  • 29
  • 67
  • Can you show us what `pictureData` is? – kind user Nov 17 '22 at 18:32
  • its a picture of a tree @kinduser – mattsmith5 Nov 17 '22 at 18:45
  • Show us `console.log(pictureData)` – kind user Nov 17 '22 at 18:45
  • hi @kinduser I updated the picture in console tab – mattsmith5 Nov 17 '22 at 19:14
  • @mattsmith5 Consider showing us more of your code. If the issue is not in the snippet you pasted, then no one here will be able to help you. For instance, what is `photoUrl` and `setPhotoUrl`? – Berthur Nov 21 '22 at 18:01
  • hi @Berthur its a state variable, I just added a declaration in the code sample – mattsmith5 Nov 21 '22 at 18:59
  • Is it possible for you to use a data URL instead? If so, try the function from this post to convert a Blob to a Data URL https://stackoverflow.com/questions/23150333/html5-javascript-dataurl-to-blob-blob-to-dataurl/30407959#30407959 – MrDiamond Nov 21 '22 at 19:09
  • Are you using create-react-app or is there any other build tool like Vite? I'll share the links for the both so that you should take a look at them or ping me with the one you use in order to get an answer as a broader topic. Here is for the [Vite](https://vitejs.dev/guide/assets.html) and here is for [Webpack](https://webpack.js.org/guides/asset-management/#loading-images) – Erhan Yaşar Nov 22 '22 at 22:06

1 Answers1

2

The URL created by invoking URL.createObjectURL() is a blob URL and its protocol is always blob:.

The URL that you showed in your question is not a blob URL created using that method because its protocol is http:.

I've included a working example in a code snippet below. It will create an object URL from image blob data, and then render the URL as a string, also using it as the source for rendering an actual image. You can use the code as a model to reproduce success.

<style>.avatar { height: 150px; width: 150px; }</style>
<div id="root"></div><script src="https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.development.js"></script><script src="https://cdn.jsdelivr.net/npm/react-dom@18.2.0/umd/react-dom.development.js"></script><script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.20.4/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">

// This Stack Overflow snippet uses UMD modules
const {StrictMode, useEffect, useState} = React;

// Since the Stack Overflow code snippet doesn't have access to your server,
// here is a function for fetching your example image data as a blob
async function fetchImageBlob (): Promise<Blob> {
  const response = await fetch('https://i.imgur.com/uSvshvJ.jpg');
  if (!response.ok) throw new Error('Response not OK');
  return response.blob();
}

function App (): React.ReactElement {
  const [objUrl, setObjUrl] = useState<string | undefined>();
  
  useEffect(() => void (async () => {
    if (objUrl) return;
    const blob = await fetchImageBlob();
    const oUrl = URL.createObjectURL(blob);
    setObjUrl(oUrl);
  })(), [objUrl]);

  return objUrl
    ? (
      <div>
        <pre><code>{objUrl}</code></pre>
        <img className="avatar" src={objUrl}></img>
      </div>
    )
    : (<div>Loading image...</div>);
}

const reactRoot = ReactDOM.createRoot(document.getElementById('root')!);

reactRoot.render(
  <StrictMode>
    <App />
  </StrictMode>
);

</script>

Code in the TypeScript Playground

jsejcksn
  • 27,667
  • 4
  • 38
  • 62