Accessing File from Function / Deployment

Hi all, a bit new to web development!

I am using Netlify to host my github repo and I am trying to send an attachment via email using nodemailer in my submission-created.js:

let replyMailOptions = {
        from: GMAIL,
        to: mail,
        subject: `My Test Subject`,
        html: `<p>a message</p>`,
        attachments: {
            path: './test.txt'
        }
    };

but it isn’t locating the file. I’ve tried placing the file under /functions/test.txt, under a subfolder /functions/test/test.txt as well as /assets/test.txt. I’ve tried to view the files under the current folder with

fs.readdir(__dirname, (err, files) => {
    files.forEach(file => {
      console.log(file);
    });
  });

I’ve also tried to copy the code from here: netlify-functions-cra-example/read-file.js at master · talves/netlify-functions-cra-example · GitHub but I am getting file not found. Specifically - "Invoke Error {“errorType”:“Error”,“errorMessage”:“Cannot find module ‘./test.txt’\n”

I keep going down rabbit holes and not sure which path leads me to what I want. Some of these examples being: build configurations (something about my relative/absolute paths?), Netlify’s “backend” options, large media, site generators and I’m getting overwhelmed and feel like I might be overcomplicating a simple solution.

Any help is much appreciated!

Hey @Steven,
Here’s an example where I accessed a pdf in a function:

// function.js

const path = require("path");
const fs = require("fs");

exports.handler = async function () {
  console.log(path.resolve(__dirname + "/rfc2468.pdf"));
  const pathToPDF = path.resolve(__dirname + "/rfc2468.pdf");
  console.log(fs.existsSync(pathToPDF));
  const pdf = fs.readFileSync(pathToPDF);

  try {
    return {
      statusCode: 200,
      headers: { "Content-type": "application/pdf" },
      isBase64Encoded: true,
      body: pdf.toString("base64"),
    };
  } catch (err) {
    return {
      statusCode: 500,
      body: err.toString(),
    };
  }
};

Both the function and the file were at the same level in my functions directory, so:

functions/
  |-thisFunction
  |---- function.js
  |---- file.pdf
  |---- ...
  |-anotherFunction/
...

Let us know if something like that would work for you

Thanks a lot @jen ! Your example gave me what I needed to line things up and fix my problems.

Actually, scratch that… :cold_face:
Looks like it worked on my local dev environment, but not working on prod.
I am getting error message
[Error: ENOENT: no such file or directory, open '/var/task/src/functions/test.pdf']

Before this I am assigning and logging this and it seems to work on prod:
let contents = path.resolve(__dirname + “/test.pdf”);
console.log(path.resolve(contents));

I found another post with a similar issue:

I’ve tried to imitate the solution by requiring it but it returns an empty object.

const pdfFile = require("./test.pdf");
console.log(pdfFile); //{}

Found the solution. Looks like functions within subdirectories are bundled with others within. I tried this initially but wouldn’t build the sub-directory functions, so I thought this wasn’t the solution. The solution was to name the subfolder the same as the function name. functions/myfunc/myfunc.js

1 Like

thank you for sharing, steven!