Upload files on column from API's Monday using Node.js

Hello Monday Team!

I previously used API-Monday for simple forms (text only), but now I need to improve my form with file uploads to CRM.

Here is my previous code for a form only with simple input.text fields:

const fetch = require('node-fetch');

const API_TOKEN =  'API_TOKEN ';

module.exports = async (req, res) => {
  const { BOARD_ID, GROUP_ID, itemName, values } = req.body;

  var jsonResponse = {};
  const columnValues = JSON.stringify(values).replace(/"/g, '\\"');

  try {
    const response = await fetch('https://api.monday.com/v2/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: API_TOKEN,
      },
      body: JSON.stringify({
        query: `
          mutation {
            create_item(board_id: ${BOARD_ID}, group_id: ${GROUP_ID}, item_name: "${itemName}", column_values: "${columnValues}") {
              id
            }
          }
        `,
      }),
    });
    jsonResponse = await response.json();
    if (jsonResponse.errors || jsonResponse.status_code === 500) {
      throw new Error('Oops, something went wrong');
    }
  } catch (error) {
    return res
      .status(error.statusCode || 500)
      .json({ error: error.message, dataError: jsonResponse });
  }

  return res.status(200).json({ success: true, data: jsonResponse });
};

And it works - perfectly!

But I’m having trouble uploading the files. I’ve read the documentation - Files, both GraphQL and Javascript tabs, but it’s not clear to me how to properly convert the file if I get it from an HTML form.
Here is my client code:

    const fileData = new FormData();
    const fileField = document.querySelector('input[type="file"]');
    fileData.append('file', fileField.files[0]);

    await fetch('/api/monday-asset', {
      method: 'POST',
      body: fileData,
    });

Here is my server-code:

'use strict';
const fetch = require('node-fetch');
const Busboy = require('busboy');

const API_TOKEN = "API_TOKEN ";

const itemID = 1710448354;

module.exports = async (req, res) => {
  var jsonResponse = {};
  const busboy = new Busboy({ headers: req.headers });

  busboy.on('file', async function (fieldname, file, filename, encoding, mimetype) {
    console.log('File', fieldname, file, filename, encoding, mimetype);

    try {
      const response = await fetch('https://api.monday.com/v2/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: API_TOKEN,
        },
        body: JSON.stringify({
          query: `
            mutation {
              add_file_to_column (item_id: ${itemID}, column_id: "files", file: ${file}) {
                id
              }
            }
          `,
        }),
      });
      jsonResponse = await response.json();
      if (jsonResponse.errors || jsonResponse.status_code === 500) {
        throw new Error('Oops, something went wrong');
      }
    } catch (error) {
      return res
        .status(error.statusCode || 500)
        .json({ error: error.message, dataError: jsonResponse });
    }

    return res.status(200).json({ success: true, data: jsonResponse });
  });

  req.pipe(busboy);
};

I’ve also checked this link - file-upload-fetch/uploader.js at main · AlexSavchuk-hash/file-upload-fetch · GitHub
But in this example the file is taken from the local system, not from request and it’s not clear how to do that correctly from this output (File):

FileStream {
  _readableState: ReadableState {
    objectMode: false,
    highWaterMark: 16384,
    buffer: BufferList { head: null, tail: null, length: 0 },
    length: 0,
    pipes: [],
    flowing: null,
    ended: false,
    endEmitted: false,
    reading: false,
    constructed: true,
    sync: true,
    needReadable: false,
    emittedReadable: false,
    readableListening: false,
    resumeScheduled: false,
    errorEmitted: false,
    emitClose: true,
    autoDestroy: true,
    destroyed: false,
    errored: null,
    closed: false,
    closeEmitted: false,
    defaultEncoding: 'utf8',
    awaitDrainWriters: null,
    multiAwaitDrain: false,
    readingMore: false,
    decoder: null,
    encoding: null,
    [Symbol(kPaused)]: null
  },

Would be glad if you can propose the full-example, with HTML-Form + input type file or showing how to transform File data from “FormData”.
Thanks!

hi @devhance

Welcome to the community. To upload a file to monday you have to send the binary data. It is not possible to send a link without downloading the file first. See alseo: Upload files on column from monday API using PHP - #9 by preetamkumarjoshi

1 Like

Hey @devhance :wave:

That’s a great question! I can confirm @basdebruin’s response here. Perhaps you could use a node module like Multer or form-data to store the file, get the binary data output and then send that to monday.com.

I hope this helps as a general poitner!

-Alex