jimp-dev / jimp

An image processing library written entirely in JavaScript for Node, with zero external or native dependencies.
http://jimp-dev.github.io/jimp/
MIT License
13.89k stars 761 forks source link

One possible solution for "Error: Could not find MIME for Buffer <null>" #922

Closed ecofriend closed 1 year ago

ecofriend commented 4 years ago

I wasn't sure where to post this exactly. This may be just a hack. If there's a better solution, I'd appreciate knowing about it.

Expected Behavior

I'm uploading a file using Apollo (GraphQL), then trying to read an image file using Jimp and resize it.

Un-expected/wanted Behavior

I was getting "Error: Could not find MIME for Buffer "

Solution

I wrapped my jimp code block in a setTimeout like below and that fixed the problem

fileUpload: async (parent, args) => {
      const file = await args.file;
      const filename = `user-${args.uid}.jpg`;
      const filePath = path.join(__dirname, `../../tmp/${filename}`);

      console.log(filePath);

      await file.createReadStream().pipe(createWriteStream(filePath));

setTimeout(() => {
      jimp
        .read(`tmp/${filename}`)
        .then(image => {
          image.cover(400, 400);
          image.writeAsync(`uploads/${filename}`, jimp.AUTO);
        })
        .catch(error => {
          throw new Error(error);
        });
}, 500);

      return file;
    }
joshuajeschek commented 3 years ago

I've just run into the same problem, on my local windows machine it works, but when running it on Ubuntu 18.04.5, I get the same error.

Have you found a better solution yet?

ecofriend commented 3 years ago

Here's my updated code that seems to work better than what I posted above. Hope this helps. ALl the best.

` const { promisify } = require('util');

profilePicUpload: async (parent, args) => {

  // have to await file file is uploaded

  const { createReadStream } = await args.file;
  const fileStream = createReadStream();
  const fileName = `user-${args.uid}.jpg`;
  const tmpFilePath = path.join(__dirname, `../../tmp/${fileName}`);
  const tmpFileStream = createWriteStream(tmpFilePath, { encoding: 'binary' });

  const user = await User.findById(args.uid);
  const currProfilePic = user.profileImg;
  const currImgFilePath = path.join(
    __dirname,
    `../../static${user.profileImg}`
  );

  user.errs = [];

  const finished = promisify(stream.finished);

  fileStream.setEncoding('binary');

  for await (const chunk of fileStream) {
    if (!tmpFileStream.write(chunk)) {
      await once(tmpFileStream, 'drain');
    }
  }

  tmpFileStream.end(() => {
    jimp
      .read(`tmp/${fileName}`)
      .then(image => {
        image.cover(300, 300).quality(60);
        image.writeAsync(`static/uploads/users/${fileName}`, jimp.AUTO);
      })
      .then(() => {
        unlink(tmpFilePath, error => {
          user.errs.push(error);
        });
        if (currProfilePic !== '/uploads/users/user.png') {
          unlink(currImgFilePath, error => {
            if (error && error.errno === -4058) {
              user.errs.push('Existing profile image not found.');
            }
          });
        }
      })
      .catch(error => {
        throw new Error(error);
      });
  });

  await finished(tmpFileStream);

}`

joshuajeschek commented 3 years ago

Thank you very much! I will look into implementing something similar, even though the whole error is still a bit weird to me.

Flowr-es commented 2 years ago

I guess an easy fix would be to allow an syntetic path as "option". Currently the bitmap is getting parsed with the path defined as null. If this could be also a syntetic path, there would be a suitable workaround for a lot of people who are facing the issue that the file type can't be read from the buffer ...