multipartform-datahapijimp

How do I pass an uploaded Image to Jimp using Hapi 19?


We're upgrading our Front-end and have reached a rather old piece of code which allows us to upload an image file to the back-end to be used as an avatar.

After some wrangling we have managed to persuade the Vue.js front-end to pass an image to the back-end via FormData.

The issue is that the handler is supposed to use Jimp to resize the image and place copies in specific directories. Unfortunately the resized images come our as 0 bytes.

Our upload route

module.exports = {
  name: 'Upload Routes',
  register: async (server, options) => {
    server.route([
      {
        method: 'PUT',
        path: '/uploads/user/{md_ref}/image',
        handler: handleUpload,
        options: {
          payload: {
            allow: 'multipart/form-data',
            maxBytes: 209715200,
            multipart: true,
            output: 'file',
            uploads: './src/public/images/uploads',
            parse: true
          }
        }
      }
    ])
  }
}

And the handler

async function handleUpload (req, h) {
  try {
    const path400 = './src/public/images/400/'
    const path200 = './src/public/images/200/'
    const path100 = './src/public/images/100/'
    const payload = req.payload
    const newImage = await Jimp.read(payload.file.path)
    await newImage.write(`${path400}${payload.file.filename}`)
    await newImage.write(`${path200}${payload.file.filename}`)
    await newImage.write(`${path100}${payload.file.filename}`)
    ...

We know that the image is being correctly uploaded to ./src/public/images/uploads - if we rename it back to filename.jpg then we have a duplicate of the original.

Jimp appears to read newImage from payload.file.path as we can inspect newImage and see the correct dimensions etc. However whilst the write() function creates the new files in thec correct directories, they are all 0 bytes.

Any ideas?


Solution

  • So it turns out that Jimp has been updated since the back-end was written (not really a surprise)

    The solution is to use .writeAsync() when using await and not .write()

    So the code above (abbreviated for a single write) should be

    const path400 = './src/public/images/400/'
    const payload = req.payload
    const newImage = await Jimp.read(`${payload.file.path})
    await newImage.writeAsync(`${path400}${payload.file.filename}`)