'Temporary directory in node not working randomly. Works sometimes but not others
I am using GCP functions in a Firebase web app. I am having trouble accessing the tmp directory properly. What I am doing incorrectly? (The odd thing is that the code seems to also work randomly.)
const tmp = os.tmpdir();
const PdfPrinter = require('pdfmake');
const fs = require('fs');
const tmp = os.tmpdir()
const dd = []
const pdfDoc = printer.createPdfKitDocument(dd);
pdfDoc.pipe(fs.createWriteStream(`${tmp}/relative.pdf`));
pdfDoc.end();
const attachment = fs.readFileSync(`${tmp}/relative.pdf`).toString("base64"); // error here
Error:
Error: ENOENT: no such file or directory, open '/tmp/relative.pdf'
at Object.openSync (node:fs:585:3)
at Object.readFileSync (node:fs:453:35)
at /workspace/index.js:494:27
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Solution 1:[1]
Here is the answer I ended up going with. I had two attachments which I needed to wait until they were complete.
I ended up switching to using Buffer, but I think I could have used the tmp directory and it would have worked. Essentially, the function was just closing down before it was finished running. So, I set up some checks to make sure everything was finished.
const docDefinition = {
// normal doc definition
}
const pdfDoc = printer.createPdfKitDocument(docDefinition);
const pdfTitle = workOrder.replace(/[^a-zA-Z0-9 ]/g, '')
pdfDoc.on('data', (chunk) => {
chunks.push(chunk);
});
let attachment
pdfDoc.on('end', () => {
const result = Buffer.concat(chunks);
attachment = {
content: result.toString('base64'),
filename: `Estimate-${pdfTitle}.pdf`,
type: "application/pdf",
disposition: "attachment"
}
});
pdfDoc.on('error', (err) => {
console.log(err);
});
pdfDoc.end();
const printer_2 = new Printer(fontDescriptors);
const chunks_2 = [];
const docDefinition_2 = {
// normal doc definition
}
const pdfDoc_2 = printer_2.createPdfKitDocument(docDefinition_2);
pdfDoc_2.on('data', (chunk) => {
chunks_2.push(chunk);
});
let attachment_2
pdfDoc_2.on('end', () => {
const result_2 = Buffer.concat(chunks_2)
attachment_2 = {
content: result_2.toString('base64'),
filename: `Lumber-order-${pdfTitle}.pdf`,
type: "application/pdf",
disposition: "attachment"
}
});
pdfDoc_2.on('error', (err) => {
console.log(err);
});
pdfDoc_2.end();
functions.logger.log('Log Before Interval Start')
This chunk of code makes sure that the function doesn't terminate before the two attachments are ready.
async function waitUntil() {
return await new Promise(resolve => {
const interval = setInterval(() => {
if (attachment && attachment_2) {
clearInterval(interval)
functions.logger.log('Attachments Ready')
let attachments = []
attachments.push(attachment)
attachments.push(attachment_2)
const msg = {
// to, from, etc.. here
attachments: attachments
};
resolve(msg)
}
}, 1000)
})
}
const msg = await waitUntil()
const resp = await sgMail.send(msg)
Solution 2:[2]
I had a very similar issue. I created a xlsx file with the framework excel4node and then I wanted to read it, to mail it as an attachment. I got the same error as you trying to read the file. Mine also worked randomly.
I could not find a reasonable solution, but adding a small delay before reading the file seems to solve it.
// Function that creates the file and stores it in the /tmp-folder
await createExcelFile()
// This solved it for me, add a small delay
await new Promise(f => setTimeout(f, 1000));
// Read the file again from tmp-folder
const pathToAttachment = "/tmp/" + reportFileName;
const attachment = fs.readFileSync(pathToAttachment).toString("base64");
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jordan |
| Solution 2 | Sunkas |
