Airtable’s attachment field is useful in lots of different scenarios and the ability to upload lots of different file types makes Airtable a great library tool for pretty much anything. But…the process of getting your files into Airtable can sometime be a bit slow - get the file on your computer, find the record in Airtable, drag the file onto the attachment field of the record, then repeat.

If you are making an archive of files from the public web, the process is even slower as you have to download the files before uploading to Airtable, but we can speed this up if you know the URL of the file that you want to put into your base.

Let’s say my base has a URL of a file I want to upload and an empty attachment field that we want to populate with the file object:

In this post we’ll create a script that loops through all of the records and attaches the file at the URL to our record in the base.

In my example data set, the URLs are images from Amazon’s website, but the URLs could be for PDFs, Word documents, XML files, JSON files or many other file types.

We’ll start the script in usual way by defining the table and a query on it:


let table = base.getTable('Table 1');
let query = await table.selectRecordsAsync();

We then want to look through the records return by the query, so we’ll do this with a for loop:


for (let record of query.records) {
  // do something here
}

Our table might have 100s or 1000s of records and we don’t want to update records which already have an attachment, so the next part of our script will check if the record already has an attachment and, if it does, then ignore it:


for (let record of query.records) {
    if (!record.getCellValue('Attachment')) {
	// do the attachment work here
    }
}

Here we’re using the “logical NOT” or “bang” operator to say:

“if NOT attachment” or “if the attachment field is empty”.

So, for each record in the loop, if there isn’t an attachment already we’re going to use the updateRecordAsync method to set the attachment field using the URL field:


for (let record of query.records) {
    if (!record.getCellValue('Attachment')) {
        await table.updateRecordAsync(record, {
            Attachment: [{
                url: record.getCellValue('Image URL')
            }]
        })
        output.text('Attachment added!');
    }
}

An attachment field takes an array of objects (remember that an attachment field could hold multiple files, hence an array). From the scripting docs:

New attachments only require the url property. You can optionally pass the filename property to give it a readable name.

Our (single) object in this case is:


{
    url: record.getCellValue('Image URL')
}

and we wrap this in square brackets to form the array. Finally, we add some output.text to let the user know when an attachment has been added.

Putting that all together, the final script is:


let table = base.getTable('Table 1');
let query = await table.selectRecordsAsync();

for (let record of query.records) {
    if (!record.getCellValue('Attachment')) {
        await table.updateRecordAsync(record, {
            Attachment: [{
                url: record.getCellValue('Image URL')
            }]
        })
        output.text('Attachment added!');
    }
}

and the result in the base will be something like this: