Uppy: Read image dimensions

Created on 17 Feb 2019  路  8Comments  路  Source: transloadit/uppy

Hello, and thanks for the great lib!

Is there a way to access the image dimensions within Uppy without need to go through a Blob -> FileReader -> Image conversion? I was unable to find a width/height metadata fields on the objects returned by the upload-success and complete events.

I'm currently doing this like so:

// convert the blob URL to an object
let objFile = await fetch(elem.preview)
let objBlob = await objFile.blob()

// convert it to a data URI
let reader = new FileReader()
reader.readAsDataURL(objBlob)

reader.onload = e => {
  // retrieve the image dimensions
  let image = new Image()
  image.src = e.target.result

  image.onload = (loadEvent) => {
    // all done
    resolve({
      thumbnail: e.target.result,
      url: elem.uploadURL,
      width: loadEvent.path[0].width,
      height: loadEvent.path[0].height,
      aspectRatio: loadEvent.path[0].width / loadEvent.path[0].height
    })
  }
}

Most helpful comment

Indeed uppy doesn't have these built in. It would be possible to do with a plugin.

For the Blob/FileReader dance, the easier thing to do is to use URL.createObjectURL, which saves a few steps:

uppy.on('file-added', (file) => {
  const data = file.data // is a Blob instance
  const url = URL.createObjectURL(data)
  const image = new Image()
  image.src = url
  image.onload = () => {
    uppy.setFileMeta(file.id, { width: image.width, height: image.height })
    URL.revokeObjectURL(url)
  }
})

As for the .preview property, it's already a blob URL, which can be assigned directly to an Image's .src:

const image = new Image()
image.src = file.preview
image.onload = () => { ... }

Then you do not need the URL.createObjectURL and URL.revokeObjectURL calls.

All 8 comments

Related: It would be also nice to add the image dimensions as a restriction.

Indeed uppy doesn't have these built in. It would be possible to do with a plugin.

For the Blob/FileReader dance, the easier thing to do is to use URL.createObjectURL, which saves a few steps:

uppy.on('file-added', (file) => {
  const data = file.data // is a Blob instance
  const url = URL.createObjectURL(data)
  const image = new Image()
  image.src = url
  image.onload = () => {
    uppy.setFileMeta(file.id, { width: image.width, height: image.height })
    URL.revokeObjectURL(url)
  }
})

As for the .preview property, it's already a blob URL, which can be assigned directly to an Image's .src:

const image = new Image()
image.src = file.preview
image.onload = () => { ... }

Then you do not need the URL.createObjectURL and URL.revokeObjectURL calls.

Thanks @goto-bus-stop for the comprehensive solution!

How to achieve this for a remote file eg Facebook or Intagram?

@RohiniJindam Unfortunately that is not possible, since there is no way to download remote files to the browser.

@goto-bus-stop thanks for the quick reply.
This works:

this.uppy.on('file-added', (file) => {
         const data = file.data 
          const url = data.thumbnail?data.thumbnail:URL.createObjectURL(data)
          const image = new Image()
          image.src = url         
          image.onload = () => {
              uppy.setFileMeta(file.id, { width: image.width, height: image.height })
              URL.revokeObjectURL(url)
          }
          image.onerror = () => {             
             URL.revokeObjectURL(url)
          }

Do you see any issues here?

That kinda works, but note that the data.thumbnail for a remote file is not the same size as the original file.

So preprocessors also cannot work for remote files? This plugin for example Image Processor Plugin @goto-bus-stop

Was this page helpful?
0 / 5 - 0 ratings