0

I am using Node.js, Express, NodeMailer, and JIMP to try to email an image after a POST. Sending an email with a completed image works when requests are spaced out but when I send multiple, sometimes old images are sent instead or partial images. I decided to cut out email for the moment and just do res.sendFile(myImage) to test that JIMP is finishing its work before the next line is called. This results in partial images being displayed and I'm not sure why?

I also get the error:

Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH

The relevant code is below.

var Jimp = require('jimp');


app.post('/invite/:email/:name', async (req,res) => {
  try {
    var email = atob(req.params.email);
    var name = atob(req.params.name);
    var data = req.body;
    const inviteImage = await makeImg(name, data);
    res.type('png')
    res.sendFile(__dirname+`/${inviteImage}`);
  } catch (error) {
    return next(error);
  }
});


async function makeImg(name, data) {
  try {
    let name2 = data["Name"];
    let style = data["Style"];
    let fanciness = data["Fanciness"];
    let dressMsg = dress(fanciness);
    let dateTime = data["Date"];
    let regex = /([0-9]+)\-([0-9]+)\-([0-9]+)T([0-9]+\:[0-9]+)/;
    let match = dateTime.match(regex);
    let ordinal = getOrdinal(match[3][1]);
    let month = getMonth(match[2]);
    let date = `${match[3]}${ordinal} ${month} ${match[1]}`;
    let time = `Time: ${match[4]}`;
    
    let smallFontName;
    let largeFontName;
    let image;
    let filename = "";
    if(fanciness <= 3){
      image = await Jimp.read('./imgs/casualTemplate.png');
      filename = "Casual";
      smallFontName = Jimp.FONT_SANS_64_WHITE;
      largeFontName = Jimp.FONT_SANS_128_WHITE;
    }else if(fanciness > 3){
      image = await Jimp.read('./imgs/fancyTemplate.png');
      filename = "Fancy";
      smallFontName = Jimp.FONT_SANS_64_BLACK;
      largeFontName = Jimp.FONT_SANS_128_BLACK;
    }

    let width = image.bitmap.width;

    let [smallFont, largeFont] = await Promise.all([Jimp.loadFont(smallFontName), Jimp.loadFont(largeFontName)]);
    
    // Print Greeting
    await image.print(smallFont, (width-650)/2, 162, {
      text: `${name} invites ${name2} To:`,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_TOP
    }, 650, 162);

    // Print Date Activity
    await image.print(largeFont, (width-810)/2, 340, {
      text: `${style}`,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_CENTER
    }, 810, 505);
    
    // Print Dress fanciness
    await image.print(smallFont, (width-810)/2, 970, {
      text: dressMsg,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_TOP
    }, 810, 66);

    // Print date of the date
    await image.print(smallFont, (width-810)/2, 1080, {
      text: `${date}`,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_TOP
    }, 810, 66);

    // Print time of the date
    await image.print(smallFont, (width-810)/2, 1187, {
      text: `${time}`,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_TOP
    }, 810, 66);

    await image.writeAsync(`./a${filename}Invite.png`);
    
    return `a${filename}Invite.png`;
  } catch(err) {
    console.log(err);
  }
}

Only the top of the image has rendered and saved, the grey shows how much more was left undone:enter image description here

Loom
  • 21
  • 2
  • 2
    Looks like you're reusing the same filename instead of generating a unique one each time, so concurrent requests are mangling the file. – robertklep Jun 25 '22 at 06:21
  • I thought Node.js uses like a queue and handles one POST request at a time – Loom Jun 26 '22 at 15:33
  • No, that's not at all how Node.js works. It can handle many (hundreds/thousands) of concurrent requests. – robertklep Jun 26 '22 at 15:49

0 Answers0