Philippe
Philippe

Reputation: 210

Fileupload - Get image resolution

I am trying to get the resolution (height, width) of the images I am sending to the backend. Attention, in this example several images are sent to the backend at once. So, we are working with loops!

I tried to find a solution in the backend, but couldn't find anything. Here is the corresponding stackoverflow question I asked.

Now I am asking for a way to do this in the frontend. When I console.log(file) following example will be outputed:

lastModified: 1657671728196
lastModifiedDate: Wed Jul 13 2022 02:22:08 GMT+0200 (Mitteleuropäische Sommerzeit) {}
name: "Example.png"
size: 3128
type: "image/png"
webkitRelativePath: ""

Too bad that the resolution is not callable this way. Furthermore I would like to save the img-type in the db but not as image/png but as png or jpeg etc. only.

async submitFiles() {
      const formData = new FormData()

      for (let i = 0; i < this.files.length; i++) {
        const file = this.files[i]
        formData.append('files', file)

        console.log(file)
      }

      try {
        const response = await this.$axios.post('/api/upload-files', formData, {
          headers: { 'Content-Type': 'multipart/form-data' },
          onUploadProgress: (progressEvent) => {
            this.uploadPercentage = parseInt(
              Math.round((progressEvent.loaded / progressEvent.total) * 100)
            )
          },
        })

        const result = response.data

        if (result.success) {
          if (this.uploadPercentage === 100) {
            this.$nuxt.refresh()
            this.$emit('exit', true)
          }
        }
      } catch (err) {
        console.log(err)
      }
    },

Upvotes: 0

Views: 691

Answers (1)

akopyl
akopyl

Reputation: 299

Checking for resolution in the browser is pretty straightforward. All you need to do is create an Image element out of the user provided file.

export default {
  data() {
    return {
      files: [],
      formData: null
    }
  },
  watch: {
    formData() {
      if (this.formData.getAll('files').length === this.files.length) {
        this.submitFiles()
      }
    },
  },
  mounted() {
    this.formData = new FormData()
  },
  methods: {
    async submitFiles() {
      try {
        const data = this.formData
        const response = await this.$axios.post(
          '/api/upload-files', data,
          {
            headers: { 'Content-Type': 'multipart/form-data' },
            onUploadProgress: (progressEvent) => {
              this.uploadPercentage = parseInt(
                Math.round((progressEvent.loaded / progressEvent.total) * 100)
              )
            },
          }
        )

        const result = response.data

        if (result.success) {
          if (this.uploadPercentage === 100) {
            this.$nuxt.refresh()
            this.$emit('exit', true)
          }
        }
      } catch (err) {
        console.log(err)
      }
    },
    processFiles() {
      for (let i = 0; i < this.files.length; i++) {
        const file = this.files[i]

        const img = new Image()
        const vm = this
        img.onload = function () {
          file.width = this.width
          file.height = this.height
          console.log(file)
          vm.formData.append('files', file)
        }
        img.src = URL.createObjectURL(file)
      }
    },
  },
}

As for the mime type of the image you could split the string by / and save the right half:

const [,type] = file.type.split('/')

EDIT: The callbacks will not be called when you try to post your data (inside the try block), so it would be a good idea to watch the formData until it's length matches the length of the files array. Then we know all of the images are processed and it's safe to send data to our backend.

Upvotes: 1

Related Questions