Skip to main content

I have registration forms that collect a digital signature. It imports into airtable as a url, like this: (https://s3.amazonaws.com/files.formstack.com/uploads/3669579/85172110/582992994/signature_85172110.png)



Can someone help me with a script that would convert this to an image attachment?

I’m not a developer, but I know a script - from a toolkit (paid plan, however) - that’ll fix you problem : https://miniextensions.com/convert-urls-to-attachments/ ( from miniextensions.com ).



Hope that’s helpful! 🙂


You can write a URL to an attachment field, like so:



// Change the names of this table/fields according to your base.

let submissionsTable = base.getTable('Form submissions');

let urlField = submissionsTable.getField('Signature URL');

let attachmentField = submissionsTable.getField('Signature attachment');



let submissionsQuery = await submissionsTable.selectRecordsAsync();

let updates = [];

for (let record of submissionsQuery.records) {

let url = record.getCellValue(urlField);

let attachments = record.getCellValue(attachmentField);



// If this record already has an attachment, skip it.

if (attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.

updates.push({

id: record.id,

fields: {

[attachmentField.id]: [{url: url}]

}

});

}



// Update records in batches of 50.

while (updates.length > 0) {

await submissionsTable.updateRecordsAsync(updates.slice(0, 50));

updates = updates.slice(50);

}


You can write a URL to an attachment field, like so:



// Change the names of this table/fields according to your base.

let submissionsTable = base.getTable('Form submissions');

let urlField = submissionsTable.getField('Signature URL');

let attachmentField = submissionsTable.getField('Signature attachment');



let submissionsQuery = await submissionsTable.selectRecordsAsync();

let updates = [];

for (let record of submissionsQuery.records) {

let url = record.getCellValue(urlField);

let attachments = record.getCellValue(attachmentField);



// If this record already has an attachment, skip it.

if (attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.

updates.push({

id: record.id,

fields: {

[attachmentField.id]: [{url: url}]

}

});

}



// Update records in batches of 50.

while (updates.length > 0) {

await submissionsTable.updateRecordsAsync(updates.slice(0, 50));

updates = updates.slice(50);

}


Thanks Stephen! This is fantastic


Thanks Stephen! This is fantastic


Glad to hear you find this snippet helpful! One minor revision — my original post was missing await in the last section of the script. I’ve updated it.


You can write a URL to an attachment field, like so:



// Change the names of this table/fields according to your base.

let submissionsTable = base.getTable('Form submissions');

let urlField = submissionsTable.getField('Signature URL');

let attachmentField = submissionsTable.getField('Signature attachment');



let submissionsQuery = await submissionsTable.selectRecordsAsync();

let updates = [];

for (let record of submissionsQuery.records) {

let url = record.getCellValue(urlField);

let attachments = record.getCellValue(attachmentField);



// If this record already has an attachment, skip it.

if (attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.

updates.push({

id: record.id,

fields: {

[attachmentField.id]: [{url: url}]

}

});

}



// Update records in batches of 50.

while (updates.length > 0) {

await submissionsTable.updateRecordsAsync(updates.slice(0, 50));

updates = updates.slice(50);

}


Hi Stephen,


I am getting an error 😦


What am I doing wrong?







Hi Stephen,


I am getting an error 😦


What am I doing wrong?







This script assumes that the URLs are always filled. To handle this case, try replacing lines 13-15 with the following:



if (url === null || attachments !== null) {

continue;

}



This will tell the script to skip records without anything in the W1 field.



Let me know if this works!


This script assumes that the URLs are always filled. To handle this case, try replacing lines 13-15 with the following:



if (url === null || attachments !== null) {

continue;

}



This will tell the script to skip records without anything in the W1 field.



Let me know if this works!


Hi Stephen,


Thank you for the quick response.


It’s not working 😦 - see attached.


What do you think is wrong?




Hi Stephen,


Thank you for the quick response.


It’s not working 😦 - see attached.


What do you think is wrong?




I think the condition needs to be if (url === null || attachments !== null) {



In other words, skip it if the URL is blank, or if there are already attachments.




Hi Kasra,


Thank you for you answer.


It seems to “pass” but now it is showing a new error (see attached) - what’s wrong?




Please paste the code here, it’s hard to tell from the screenshot.


Please paste the code here, it’s hard to tell from the screenshot.


ERROR


SyntaxError: Unexpected token )


at new Function ()


at blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:39877


at s (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:3857)


at Generator._invoke (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:3610)


at Generator.forEach.e.(anonymous function) )as next] (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:4214)


at e (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:66)


at l (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:269)


at blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:328


at new Promise ()


at blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:209


ERROR


SyntaxError: Unexpected token )


at new Function ()


at blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:39877


at s (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:3857)


at Generator._invoke (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:3610)


at Generator.forEach.e.(anonymous function) [as next] (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:4214)


at e (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:66)


at l (blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:269)


at blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:328


at new Promise ()


at blob:https://block--do4m-g6-a-fwxw-u-c0--af936p8.airtableblocks.com/179f68e0-4242-40a2-9035-a13fc45c478c:1:209



Please paste the code here, it’s hard to tell from the screenshot.


@Kasra What do you think?


On line 12, it should be:



// If this record already has an attachment, skip it.

if (url === null || attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.



Looks like the “continue; }” part got dropped when you updated the script.


On line 12, it should be:



// If this record already has an attachment, skip it.

if (url === null || attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.



Looks like the “continue; }” part got dropped when you updated the script.




Works Great!!!


Thank you so much @Kasra!


Just want to thank you, @Stephen_Suen and @Kasra. I’m new to javascript and have been struggling to figure this out (attempting to adapt half a dozen diff. scripts in the process).



This has solved a huge use case for me: I’m using AirTable to manage metadata for my late father’s design archives, and have been struggling with how to display image thumbnails with each record (without having to manually attach them). This script allows me to host my images on my server and pull the URL into the attachments field to display the image.



It does feel a bit redundant (since AT is now also hosting the attached image on its back-end, I assume), but it certainly solves my dilemma. I so appreciate you both sharing this code.


Just want to thank you, @Stephen_Suen and @Kasra. I’m new to javascript and have been struggling to figure this out (attempting to adapt half a dozen diff. scripts in the process).



This has solved a huge use case for me: I’m using AirTable to manage metadata for my late father’s design archives, and have been struggling with how to display image thumbnails with each record (without having to manually attach them). This script allows me to host my images on my server and pull the URL into the attachments field to display the image.



It does feel a bit redundant (since AT is now also hosting the attached image on its back-end, I assume), but it certainly solves my dilemma. I so appreciate you both sharing this code.


Jess,



It’s great to see you are becoming a scripter; the agility and opportunities to advance all data management activities will skyrocket as your scripting proficiency rises.





If you want to eliminate a bit of the redundancy and server hosting, simply create a Google Drive folder where you curate your dad’s content and set it to share to anyone with link. Then use those links to upload attachments into Airtable. This makes it far easier to organize and curate the content without exposing it to the open web where it will be indexed and broadcast to the world. It’s also far easier to upload documents into Drive than over FTP or whatever. Removing documents from the folder (should that be desired) is also easier.


You can write a URL to an attachment field, like so:



// Change the names of this table/fields according to your base.

let submissionsTable = base.getTable('Form submissions');

let urlField = submissionsTable.getField('Signature URL');

let attachmentField = submissionsTable.getField('Signature attachment');



let submissionsQuery = await submissionsTable.selectRecordsAsync();

let updates = [];

for (let record of submissionsQuery.records) {

let url = record.getCellValue(urlField);

let attachments = record.getCellValue(attachmentField);



// If this record already has an attachment, skip it.

if (attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.

updates.push({

id: record.id,

fields: {

[attachmentField.id]: [{url: url}]

}

});

}



// Update records in batches of 50.

while (updates.length > 0) {

await submissionsTable.updateRecordsAsync(updates.slice(0, 50));

updates = updates.slice(50);

}


Hi Stephen,



was going to asking help about this when luckily run into this solution.



I’d like to copy url from “turl” into “Preview” in this table https://tinyurl.com/y2lov52r



changed the script as such:


let submissionsTable = base.getTable(Video’);


let urlField = submissionsTable.getField(‘turl’);


let attachmentField = submissionsTable.getField(Preview’);



let submissionsQuery = await submissionsTable.selectRecordsAsync();


let updates = ;


for (let record of submissionsQuery.records) {


let url = record.getCellValue(urlField);


let attachments = record.getCellValue(attachmentField);



// If this record already has an attachment, skip it.

if (attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.

updates.push({

id: record.id,

fields: {

attachmentField.id]: a{url: url}]

}

});



}



// Update records in batches of 50.


while (updates.length > 0) {


await submissionsTable.updateRecordsAsync(updates.slice(0, 50));


updates = updates.slice(50);


}



and get the following error message



SyntaxError: Invalid or unexpected token


on line 1


at s on line 1


at Generator._invoke on line 1


at Generator.forEach.e.(anonymous function) oas next] on line 1


at e on line 1


at l on line 1


on line 1


on line 1



could you please help me out?


Hi Stephen,



was going to asking help about this when luckily run into this solution.



I’d like to copy url from “turl” into “Preview” in this table https://tinyurl.com/y2lov52r



changed the script as such:


let submissionsTable = base.getTable(Video’);


let urlField = submissionsTable.getField(‘turl’);


let attachmentField = submissionsTable.getField(Preview’);



let submissionsQuery = await submissionsTable.selectRecordsAsync();


let updates = ;


for (let record of submissionsQuery.records) {


let url = record.getCellValue(urlField);


let attachments = record.getCellValue(attachmentField);



// If this record already has an attachment, skip it.

if (attachments !== null) {

continue;

}



// Otherwise, attach the image at the URL.

updates.push({

id: record.id,

fields: {

attachmentField.id]: a{url: url}]

}

});



}



// Update records in batches of 50.


while (updates.length > 0) {


await submissionsTable.updateRecordsAsync(updates.slice(0, 50));


updates = updates.slice(50);


}



and get the following error message



SyntaxError: Invalid or unexpected token


on line 1


at s on line 1


at Generator._invoke on line 1


at Generator.forEach.e.(anonymous function) oas next] on line 1


at e on line 1


at l on line 1


on line 1


on line 1



could you please help me out?


Hi @Paolo_Perrone:



Lines 1 and 3 of your script are missing the single quote before the name of the table and field:



let submissionsTable = base.getTable('Video');



and



let attachmentField = submissionsTable.getField('Preview');



Adding those single quotes back should fix the error you’re seeing.


Hi! I have sooo enjoyed this script for images. But I have a PDF automatic download link like this: https://www.teacherspayteachers.com/Preview/Noun-Sort-Cut-and-Paste-083291900-1381063936?fn=valentinesdayworksheetspreview.pdf



That is NOT pulling the PDF correctly. Any ideas?


Hi! I have sooo enjoyed this script for images. But I have a PDF automatic download link like this: https://www.teacherspayteachers.com/Preview/Noun-Sort-Cut-and-Paste-083291900-1381063936?fn=valentinesdayworksheetspreview.pdf



That is NOT pulling the PDF correctly. Any ideas?




One idea - that URL is not publicly accessible, a requirement of Airtable attachments.


Ah, makes sense. Ok, thanks!


How about this? I know it is in a viewer…https://www.teacherspayteachers.com/pdfjs/view.html?file=https%3A%2F%2Fpreview-2.teacherspayteachers.com%2F0%2F944%2F944153%2F6d9dcd81962c9b98d6d16b223d687828%3Fpreview-token%3Dexp%3D1596657536~hmac%3D7376d51a55862c7f9837c6e18591f1b34907f90be611c2387ba77cb1ee6c25f9%26file_name%3Dwinterworksheetspreview.pdf




Viewers do note make it possible for a GET request to access the file. Viewers are for humans; Airtable’s attachment system is a machine.


Ha, yeah, I know. I want the impossible 🙂


Reply