How Airtable’s Blocks SDK handles attachment URLs
  • 08 Feb 2023
  • 2 Minutes to read
  • Dark
    Light

How Airtable’s Blocks SDK handles attachment URLs

  • Dark
    Light

Article Summary

On November 8, 2022, Airtable improved the security of our attachment URLs by incorporating an expiring links functionality across our product surface areas. You can read more about this behavior here.

This update included changes to the way all versions of the Blocks SDK handles attachments.

If you use the following SDK methods to obtain attachment URLs, please keep in mind that the update impacted the following:


How does the SDK handle attachment URLs today?

Attachment URLs obtained via the SDK will expire after a few hours. After those URLs expire, the Blocks SDK will refresh the URLs, pushing any expired URLs to your third-party extension. 

Starting November 8th, 2022, attachment URLs look like this:

https://v5.airtableusercontent.com/v1/3/3/1652918400000/2dxLFHD0M8rGi29amOeYiQ/RKjaja0qgtEUzIPu6HsnYbC3HPiCkiK4wfhB9**dJJJpVUlwitX0puZY9v485L0SUGnZEU3cSBDR6-wdZseNtg/hN5S51oabftFYcDU2rPOB838AzaI4u98-Wc-Li4GwB8


How did the SDK handle attachment URLs before November 8th, 2022?

Attachment URLs obtained via the SDK are persistent. Methods like getCellValue return a static URL that can be interpreted.

Attachment URLs used to look like this:

https://dl.airtable.com/.attachments/4df81a26d0a04015fa2935f99cd73014/1f055329/image_9201.jpg


How can I ensure that my block properly handles attachment URLs?

We recommend using hooks to review attachment URLs as they expire and refresh. For example, the following hooks allow you to confirm attachment URLs refresh:

// this component renders the first image from the record’s attachment field, and will automatically re-render the image when the URL is refreshed

function RenderFirstImage({table, recordId, attachmentField}) {
    // useRecordById hook watches for the attachment url refresh.
    const record = useRecordById(table, recordId);
    const imageAttachments = record.getCellValue(attachmentField);
    const coverImageAttachment = imageAttachments[0];
    const url = coverImageAttachment.url;
    const clientUrl = record.getAttachmentClientUrlFromCellValueUrl(coverImageAttachment.id, url);

 return <div>{clientUrl && <img src={clientUrl} alt="" height="100%" />}</div>;
}

In the past, it was possible to depend on the format of the attachment URL or identifiers within it (eg: filename). After the changes to attachments went live on November 8th, 2022, there is nothing in the attachment URL that can be interpreted in a meaningful way due to security considerations. To reiterate, the attachment URL formatting is not part of our compatibility surface, so users should not attempt to parse or interpret attachment field URLs.

// the following parsing logic will break because filename is no longer included in the url.
const pathComponents = attachmentUrl.split('/')
const fileName = pathComponents[pathComponents.length -1]
console.log(fileName);

Keep in mind not to use URLs as stable identifiers. Attachment URLs will refresh after a short period.

/ the following logic will download the same attachment content repeatedly, because the attachmentUrl will refresh.

// downloadedAttachmentUrlsSet is a global set storing downloaded attachment urls
if (!downloadedAttachmentUrlsSet.has(attachmentUrl)) {
downloadedAttachmentUrlsSet.add(attachmentUrl);
triggerDownloadNewAttachment(attachmentUrl);
}

In addition, do not store URLs for future usage. Any URLs you store will expire after a few hours.

import \* as fs from 'fs';
fs.writeFileSync("attachmentUrls.txt", attachmentUrl);
// some time later
const savedAttachmentUrl = fs.readFileSync("attachmentUrls.txt");
// the savedAttachmentUrl may be expired.
triggerDownLoadNewAttachment(savedAttachmentUrl);


Who can I contact if I have questions about the update?

Please reach out to Airtable Support with any questions.


Was this article helpful?