0

I wish to display an input element's selected image. Can this be performed on a local file, accessing the image client side, or would I need to upload the image to a server?

Here's my attempt in React. I can access the correct file name from the input element using inputElem.files[0].name. As soon as I am trying to set an image element to it, the broken image icon is displayed, and no error is surfaced.

const App = () => {
  // state to keep track of img elements src. The default works fine.
  const [imgSrc, setImgSrc] = useState('/images/test.jpg')

  function handleImgUpload() {
    const url = '/images/' + e.target.files[0].name
    setImgSrc(url)
    console.log(url) // /images/26e3e793-98f5-4720-9f82-8963276d5e27.JPG
  }

  function handleImgLoadSuccess() {
    console.log('image loaded!')
  }

  function handleImgLoadError() {
    console.log('image not loaded')
  }

  return (
    <div>
      <div>
        <label htmlFor="img">Select an image:</label>
        <input
          type="file"
          id="img"
          name="img"
          accept="image/png, image/jpeg"
          onChange={(e) => handleImgUpload(e)}
        />
      </div>

      <img
        src={imgSrc}
        alt="Your upload"
        onLoad={handleImgLoadSuccess}
        onError={handleImgLoadError}
      />
    </div>
  )
}

In the console, however, the url seems to be correct.

<img src="/images/26e3e793-98f5-4720-9f82-8963276d5e27.JPG" height="100" width="200" alt="Input" class="jsx-855240488">
msalla
  • 717
  • 6
  • 23

2 Answers2

0

Hey – I see what you're trying to do, but it doesn't look like this will work. You need to create a new file reader.

const showTempImage = (e) => {
    const file = e.target.files[0];
    const img = document.createElement("img");

    const reader = new FileReader();

    reader.addEventListener('load', (e) => {
        img.src = e.target.result;
    });

    reader.readAsDataURL(file);

   // Append the img tag to the dom somewhere
}
0

This did the trick by creating a correct blob url.

const inputImg = e.target.files[0]
const url = URL.createObjectURL(inputImg)
// blob:http://localhost:3000/test-img.jpg

The resulting file stays in memory and needs to be removed in order to create memory leaks.

URL.revokeObjectURL(url)

This also seems to be accomplishable with FileReader, though there are differences.

msalla
  • 717
  • 6
  • 23