Accessing attachments from Custom Widget builder

Hey everyone,

I recently got a question about how to access an image from an attachment field in Grist and display it in a custom widget. I’ll try to summarize it here for anyone interested.

To download an attachment Grist exposes an API endpoint available here.

Unfortunately, the Grist API isn’t directly accessible from the browser for security reasons, but there’s a special endpoint you can use to get a short-lived access token. This token lets you safely access attachments within your custom widget (even those built using Custom widget builder).

I’ve created a demo you can check out here: Attachments in builder - Grist

Here’s how to do it:

  1. Get the Attachment ID
    The column in Grist stores a list of attachment IDs. You can grab the first one with record.ColumnName[0].
  2. Get the Access Token
    Use grist.docApi.getAccessToken() to get a short-lived token and the base URL for the document.
  3. Build the URL
    Join the base URL, attachment ID, and token to form the full URL for the attachment data.
  4. Display the Image
    Use the URL in an <img> tag to display the image or use it in any other way you like.

Here is a very simple code that demonstrate it (part of the example above):

  grist.ready({ requiredAccess: 'full' });

  const imageEl = document.getElementById("image");

  let token = "";
  let baseUrl = "";

  function updateImageUrl(id) {
    const url = `${baseUrl}/attachments/${id}/download?auth=${token}`;
    imageEl.src = url; // Set the URL as the image source
  }

  // Get the access token and base URL
  grist.docApi.getAccessToken({ readOnly: true }).then(response => {
    token = response.token;
    baseUrl = response.baseUrl;
  });

  // Listen for changes to the current record
  grist.onRecord(record => {
    const attachmentId = record.Image?.[0]; // Get the first attachment ID
    if (attachmentId) {
      updateImageUrl(attachmentId);
    }
  });
3 Likes

Can I access an attached Excel file with this… and extract data?

Yes you can, you can access the attachment regardless of the type of file it is. It’s just a question of what you do with it. A quick and very rough version that works for accessing attached Excel files by using the sheetjs library can be found here Attachments in builder Excel eample - Grist

Hi Jarek,
Thank you for this post!
I have a question: is there any way to do the “classic” API call from a custom widget, and get a link from that to send the link by email and allow the attachment download?

Indeed, I would like to create a custom widget that allows users to visualize and send personalized emails, with the ability to add an attachment as an url.

I successfully did it using your way to build a link, until I correctly read your post ( :upside_down_face:) and realized that:

  • it was a short-lived access token, so the link wouldn’t be useful after a short time
  • sending the link to someone would allow them to access other attachments…

This is what I did so far (all credits to @Amandine_Dugrain for the css :))

And the email is sending well:

The final use case is the ability to send invoices by email.