Sending POST requests as form-data without FormData object (Airtable scripting)

Need help with file uploads in Airtable scripts

I’m working on a project that needs to upload files to a cloud service. The API wants the data sent as multipart/form-data. But I’m stuck because Airtable scripts don’t have FormData.

I usually do it like this:

let uploadData = new FormData();
uploadData.append('file', fileUrl);
uploadData.append('preset', UPLOAD_PRESET);
uploadData.append('account', CLOUD_ACCOUNT);

let result = await fetch(UPLOAD_API, {
  method: 'POST',
  body: uploadData,
});

But that won’t work here. I tried other ways to send the data, but the API only likes multipart/form-data.

Anyone know how to do this without FormData? I’m out of ideas. Thanks!

I’ve encountered this issue before when working with APIs that strictly require multipart/form-data. One workaround I found effective is using the ‘node-fetch’ library, which you can import in Airtable scripts. It provides a FormData implementation that works well in this environment.

Here’s how you could modify your code:

import fetch, { FormData } from 'node-fetch';

let uploadData = new FormData();
uploadData.append('file', fileUrl);
uploadData.append('preset', UPLOAD_PRESET);
uploadData.append('account', CLOUD_ACCOUNT);

let result = await fetch(UPLOAD_API, {
  method: 'POST',
  body: uploadData,
});

This approach maintains the simplicity of your original code while solving the FormData availability problem in Airtable scripts. Just make sure to include the necessary import statement at the top of your script.

I faced a similar challenge when working with Airtable scripts recently. Here’s what worked for me:

Instead of FormData, you can manually construct the multipart/form-data payload. It’s a bit more work, but it gets the job done. You’ll need to generate a boundary string, then build the body as a string with the correct formatting.

Here’s a rough example:

const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2);
const body = [
  `--${boundary}`,
  'Content-Disposition: form-data; name="file"',
  '',
  fileUrl,
  `--${boundary}`,
  'Content-Disposition: form-data; name="preset"',
  '',
  UPLOAD_PRESET,
  `--${boundary}`,
  'Content-Disposition: form-data; name="account"',
  '',
  CLOUD_ACCOUNT,
  `--${boundary}--`
].join('\r\n');

let result = await fetch(UPLOAD_API, {
  method: 'POST',
  headers: {
    'Content-Type': `multipart/form-data; boundary=${boundary}`
  },
  body: body
});

This approach mimics the structure of multipart/form-data without relying on FormData. It’s not as clean, but it should work with your API. Hope this helps!

hey, i ran into this problem too. one thing that worked for me was using the ‘form-urlencoded’ content type instead. it’s not exactly the same, but many apis will accept it. you could try something like this:

const data = new URLSearchParams();
data.append('file', fileUrl);
data.append('preset', UPLOAD_PRESET);
data.append('account', CLOUD_ACCOUNT);

let result = await fetch(UPLOAD_API, {
  method: 'POST',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  body: data
});

hope that helps!