Code to retrieve url in Attachments field

Hi,
Here is my code using record.get([“Attachments”]); :

function showListe() {
  base("Works")
    .select({ view: "Grid view" })
    .eachPage(function page(records) {
      records.forEach(function(record) {
        var li = document.createElement("li");  
        li.textContent = record.get(["Attachments"]);
        document.getElementById("root").appendChild(li);
      });
    });
}

which gets me :

  • [object Object]
  • [object Object]

If i do record.get([“Attachments”][“url”);
i get nothing…

Help!

Hi @DanielAssayag - in the API, an attachments field is an array of objects, so you need to:

  • do a “for each” on the array and, in the loop, access:

['Attachments'][i]['url']

for each i

  • Or, if you know you want the first attachment or if there’s only one attachment, access:

['Attachments'][0]['url']

JB

Thanks,
I still can’t make it work but it might be my code.

What about retrieving the Attachments id, or width?

Unfortunately, you’ve got the same issue. Even with one attachment, the API returns an array (in this case with one object):

[
    {
        "id": "att911J3Ml..OF2l",
        "url": "https://dl.airtable.com/.attachments/117bac5e63..466918/5e2ad89d/Screenshot2019-09-05at16.23.21.png",
        "filename": "Screenshot 2019-09-05 at 16.23.21.png",
        "size": 32212,
        "type": "image/png",
        "thumbnails": {
            "small": {
                "url": "https://dl.airtable.com/.attachmentThumbnails/bac00690d..b31218/81919b8a",
                "width": 119,
                "height": 36
            },
            "large": {
                "url": "https://dl.airtable.com/.attachmentThumbnails/6937346c0d5..37d8e5/9a38e7bb",
                "width": 1094,
                "height": 330
            },
            "full": {
                "url": "https://dl.airtable.com/.attachmentThumbnails/9747be1d8c7..558f689c89/7e632201",
                "width": 3000,
                "height": 3000
            }
        }
    }
]

So you’ve still got to loop through the array and use the array index to get anything

Out of interest why are you doing record.get there? Isn’t it something like:

record.Attachments[0].url

I’m assuming you’re in JS there and I’m only a moderately good coder, so I might be talking out of my hat!

I dont know why, but i can get the * [object Object]
but when i use [0][“url”] it just returns nothing.

How do you retrieve the all the raw json data on the object?

Here is my current code, i’m using codesandboxio in react js to run my tests.

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

var $ = require("jquery");

var Airtable = require("airtable");
Airtable.configure({
  endpointUrl: "https://api.airtable.com",
  apiKey: "xx"
});
var base = Airtable.base("xx");

function App() {
  return (
    <div className="App">
      <div id="artworks">{loadArtworks()}</div>
    </div>
  );
}

var loadArtworks = function() {
  $("#artworks").empty();
  base("Works")
    .select({
      sort: [
        {field: 'Year', direction: 'asc'}
    ]
    })
    .eachPage(
      function page(records, fetchNextPage) {
        records.forEach(function(record) {
          var works = $("<div>");
          works.append($("<h3 class='name'>").text(record.get("Name")));
          works.append($("<div class='year'>").text(record.get(["Year"])));
          works.append($("<div class='typeofwork'>").text(record.get(["Type of work"])));
          works.append($("<div class='dimensions'>").text(record.get(["Dimensions (cm)"])));
          // nextline: this return [object Object]
          works.append($("<div class='photos'>").text(record.get(["Photos"]))); 
          // nextline: this return nothing
          works.append($("<div class='photosurl'>").text(record.get(["Photos"][0]["url"]))); 
          
          works.attr("id", record.getId());
          $("#artworks").append(works);
        });
        fetchNextPage();
      },
      function done(error) {
        console.log(error);
      }
    );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

I was able to retrieve the json:

Here is the structure of my data :

but i don’t know how to retrieve the data inside the “Photos” field (attachment type)

Um… assuming Photos is the name of the attachment-type field, the url of the first photo in the array should be…

Photos[0].url

You are not obligated to enumerate the collection of attachments in a field of type [attachment], but it is good practice because you really don’t know if there’s none, one, or more photos. Assuming Photos[0]. … is valid will be brittle and often may fail.

Whenever you see this, it’s an indication that each item in the array is javascript object notation (JSON) and it is addressable like any other JSON objects.

If you need to understand what’s inside that object, you can use JSON.parse() and JSON.stringify() to expose the data. But the dudes at Airtable have also provided stellar API documentation that will expose the attachment format as well.

Make sense?

It does,
Though i still have issues retrieving attachments (sorry for that)

Here is a function i coded to retrieve data, but i can only console.log ther records and not return it in variable to parse it json. Any idea how to do it?

function loadGeneralItems(table) { 
var recList = []
    base(table).select().all()
    .then(
       function (records)  { 
        for (let i=0; i< records.length; i++)
       recList.push(records[i]._rawJson.fields) 
      // console.log(recList) // outputs ([Object, ...])
      }); 
   // return recList // returns nothing         
}

If you are loading all the records in a table and then enumerating them only to build yet another array representing the same records, I must ask why? Why not simply return records? It is an array with all of the data - even the data that is in nested objects such as fields of type attachment.

I suspect the answer is that you are groping to find a way to access the data in your attachments. That said, allow me to demonstrate how I approach this in server-side javascript (using Google Apps Script) WITHOUT using the Airtable SDK which I believe you are using.

At the outset, there’s nothing wrong with the Airtable SDK, but because it attempts to [quietly] overcome shortfalls in the API (such as true queries), I tend to develop 100% of the code required to extract Airtable data. Color me “old-school” in this example. :wink:

For this guide, I’ll use the Airborne Search Configuration table because it contains one record with an attachment which is a 1mb ElasticSearch index document which is a full-text index of many other bases. The field IndexRef is a field of type attachment and I know that extracting values from these field types if your key challenge. Here’s what the table looks like.


As a simple starting point, consider the following function - it returns only the first page of a table (just 100 records). Passing the baseKey, tableName, and apiKey to this function returns the records as JSON text.


While the response is JSON, it is not parsed. More on that later.

Now, take a close look at this simple example that uses the API function call to get 100 records and enumerate them.


It will return a collection of records like this one:


What’s happening in the enumRecords function?

  • Line 38 retrieves a list of records in JSON format (as text).
  • Line 43 parses the JSON results text into an array of records. Note - .records is added outside the parsing function because we really only want the records node which is not accessible until we first parse the results.
  • The enumeration of the records filters for a record where IndexRef is not undefined (see line 52).
  • At line 56 we log the stringified version of the record so we can easily examine it in a JSON parser (if we want).
  • Finally, line 59 logs the attachment url value.

And the log output looks something like this:


Final Thoughts

Note how this example doesn’t have to build a new array consisting of the data to get at the attachment data. In fact, the promise of JSON is that – aside from the parsing step – it is readily consumable as soon as your app has it.

Also note the direct access to all the fields in the attachment collection; accessing this data should be no different than accessing any other data. I suspect the SDK does this for you, but it seems that its integrated helper methods is what may be confusing you. I’m also certain that using the SDK, you can build a better version of my training code and likely with fewer lines. I don’t use the SDK so I don’t have any demo code to share with you.

Lastly, as I’m sure someone will type in the attachment URL to snoop on it, I’ll save you the trouble. It’s a Lucene-inspired full text index of the demo bases in Airtable and it is fully accessible without credentials because all Airtable attachment URLs are open and accessible to everyone. :wink: Ergo, be very careful when you expose attachment URLs in any context - they are public documents.

3 Likes