0

I'm trying to upload an HEIC file with filepond. Which file type should I specify?

At the moment I have this:

  accepted-file-types="image/jpeg, image/png, image/gif, image/jpg"

I can't find anything in the docs about this, and my experimentation doesn't work.

Here's the test file I'm trying to upload:

https://github.com/tigranbs/test-heic-images/raw/master/image1.heic

Edward Hibbert
  • 107
  • 2
  • 11

2 Answers2

2

Thank to @Rik for pointers. Here is some code which does this using filepond in Vue. Feels slightly hacky but does the job.

Accept the image/heic content type and add a custom validator:

<file-pond
  v-if="supported"
  ref="pond"
  name="photo"
  :allow-multiple="multiple"
  accepted-file-types="image/jpeg, image/png, image/gif, image/jpg, image/heic"
  :file-validate-type-detect-type="validateType"
  :files="myFiles"
  image-resize-target-width="800"
  image-resize-target-height="800"
  image-crop-aspect-ratio="1"
  label-idle="Drag & Drop photos or <span class=&quot;btn btn-white ction&quot;> Browse </span>"
  :server="{ process, revert, restore, load, fetch }"
  @init="photoInit"
  @processfile="processed"
  @processfiles="allProcessed"
/>

Then in the validator check for the filename, to handle browsers that don't set the correct MIME type:

validateType(source, type) {
  const p = new Promise((resolve, reject) => {
    if (source.name.toLowerCase().indexOf('.heic') !== -1) {
      resolve('image/heic')
    } else {
      resolve(type)
    }
  })

  return p
}

Then in the process callback, spot the HEIC file and use heic2any to convert it to PNG and use that data in the upload.

async process(fieldName, file, metadata, load, error, progress, abort) {
  await this.$store.dispatch('compose/setUploading', true)

  const data = new FormData()
  const fn = file.name.toLowerCase()

  if (fn.indexOf('.heic') !== -1) {
    const blob = file.slice(0, file.size, 'image/heic')
    const png = await heic2any({ blob })
    data.append('photo', png, 'photo')
  } else {
    data.append('photo', file, 'photo')
  }

  data.append(this.imgflag, true)
  data.append('imgtype', this.imgtype)
  data.append('ocr', this.ocr)
  data.append('identify', this.identify)

  if (this.msgid) {
    data.append('msgid', this.msgid)
  } else if (this.groupid) {
    data.append('groupid', this.groupid)
  }

  const ret = await this.$axios.post(process.env.API + '/image', data, {
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUpLoadProgress: e => {
      progress(e.lengthComputable, e.loaded, e.total)
    }
  })

  if (ret.status === 200 && ret.data.ret === 0) {
    this.imageid = ret.data.id
    this.imagethumb = ret.data.paththumb
    this.image = ret.data.path

    if (this.ocr) {
      this.ocred = ret.data.ocr
    }

    if (this.identify) {
      this.identified = ret.data.items
    }

    load(ret.data.id)
  } else {
    error(
      ret.status === 200 ? ret.data.status : 'Network error ' + ret.status
    )
  }

  return {
    abort: () => {
      // We don't need to do anything - the server will tidy up hanging images.
      abort()
    }
  }
},

The server is then blissfully unaware that the original file was HEIC at all, and everything proceeds as normal.

Edward Hibbert
  • 107
  • 2
  • 11
1

The format is image/heic, I tested this using this tool: https://codepen.io/rikschennink/pen/NzRvbj

It's possible that not all browsers assign the correct mime type. You can work around that by using the fileValidateTypeDetectType property see here for an example: https://pqina.nl/filepond/docs/patterns/plugins/file-validate-type/#custom-type-detection

Please note that uploading will work, but previewing the image won't.

Rik
  • 3,328
  • 1
  • 20
  • 23
  • Thanks for your reply, and sorry for the delay in thanking you. I've tried that property, and that does allow me to correct the MIME type. However I then have problems on the server side, since I'm running PHP imagecreatefromstring, which doesn't handle HEIC files. Is there any scope for running a conversion on the client side (e.g. using https://github.com/alexcorvi/heic2any) to turn it into JPG before the upload? I'm not sure at what point I would do that. – Edward Hibbert Apr 10 '20 at 14:20
  • 1
    You could set up a custom `server.process` method and detect the HEIC format there, if found, convert the file before upload. https://pqina.nl/filepond/docs/patterns/api/server/#advanced – Rik Apr 13 '20 at 06:08
  • How do you detect and convert the HEIC image to JPG? Could any one provide an example? – Jnickz May 12 '20 at 04:40