Create Card Attachment - Error 400 Bad Request Parsing Body

Hello

I’m getting a 400 Bad Request Error parsing body when using the REST API with Node.js to create a card attachment. I’m successful at creating the card attachments in Postman, so I know my parameters and settings are correct.

I was wondering if someone could review the code below and offer advice on how to troubleshoot my issue?


const fs = require('fs');
const FormData = require('form-data');
const fetch = require('node-fetch');
const env = require('dotenv').config({ path: './config/.env' });

// const mimeType = 'text/plain';
// const fileName = 'hello-world.txt';
const APIKey = process.env.API_KEY;
const APIToken = process.env.API_TOKEN;
const cardId = "6434c3989e540614476e8627"
const url = `https://api.trello.com/1/cards/${cardId}/attachments?key=${APIKey}&token=${APIToken}`;

const formData = new FormData();
formData.append( 'file', fs.createReadStream('./assets/hello-world.txt', 'utf-8'));

const formHeaders = formData.getHeaders();


formData.getLength((err, length) => {
  if (err) {
    console.error(err);
    return;
  }

  formHeaders['Content-Length'] = length;
  
  return fetch( url, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'multipart/form-data',
      'Content-Length': formHeaders['Content-Length'],
    },
    body: formData
  })
  .then(response => {
    console.log(
      `Response: ${response.status} ${response.statusText}`
    );
    
    return response.text();
  })
  .then(text => console.log(text))
  .catch(err => console.error(err));
});

I appreciate your help.

Martin

I’m not too familiar with Node, but are you sure createReadStream is returning or closing the stream in the way you’re expecting? I’ve known postman to give handouts in this area in some cases where they take do more than what you expect them to.

Hi @jrfischer

I think you were right.

I refactored my code and changed out the createReadStream method with the readFileSync method and after doing this got the attachment to create on the card - yay! Node isn’t my strong suit and I’m still learning. I think I had other issues in the code above as well, so I decided to take a more careful approach and console.log() each step of the way to make sure what I was passing into fetch was certain.

Here’s what worked:

const env = require('dotenv').config({ path: './config/.env' });
//console.log(process.env)
const fs = require('fs');
const FormData = require('form-data');
const fetch = require('node-fetch');

const filePath = './assets/hello-world.txt'


const getFile = async (filePath) => {
  const attachment = await fs.readFileSync( filePath, 'utf-8');
  return attachment;
}

getFile( filePath )
  .then( attachment => {

    console.log(`Attachment: ${attachment.length}`);
    const length = attachment.length;
    const formData = new FormData();
    formData.append( 'file', attachment );
    return { formData, length };

  }).then( ({formData,length}) => {

    const formHeaders = formData.getHeaders();
    formHeaders['Content-Length'] = length;
    //formHeaders['Accept'] = 'application/json';
    //formHeaders['Content-Type'] = 'multipart/form-data';

    console.log(formHeaders);

    const cardId = "642dba5837f18a2213fb3785"
    const APIKey = process.env.API_KEY;
    const APIToken = process.env.API_TOKEN;

    const url = `https://api.trello.com/1/cards/${cardId}/attachments?key=${APIKey}&token=${APIToken}`;
    console.log(url)
   
    fetch( url, {
          method: 'POST',
          headers: formHeaders,
          body: formData
        })
        .then(response => {
          console.log(response)
          console.log( `Response: ${response.status} ${response.statusText}` );
          return response.text();
        })

  }).catch(err => console.error(err));
1 Like