Downloading Attachments from a Sheet with API
Hello Smartsheet Community!
I need help downloading attachments from a sheet that currently has a little over five thousand lines and manually downloading isn't ideal.
I was able to extract the metadata for my sheet and revising the documentation for the Attachment Object I was able to extract the attachment id and other attributes but was missing the entire block which contained the url attribute.
I'm using python SDK with the code below
sheet = smartsheet_client.Sheets.get_sheet(sheet_id, include='attachments')
Alternatively I have also used
url = f"https://api.smartsheet.com/2.0/sheets/{sheet_id}?include=attachments"
headers = {
"Authorization": f"Bearer API CODE",
"Accept": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
sheet_metadata = response.json()
print(json.dumps(sheet_metadata, indent=4)) # Pretty-print the JSON response
else:
print(f"Error: {response.status_code}, {response.json()}")
This is what my metadata is returning (example):
{
"id": 0,
"parentId": 0,
"attachmentType": "BOX_COM",
"attachmentSubType": "DOCUMENT",
"mimeType": "PNG",
"parentType": "COMMENT",
"createdAt": "2019-08-24T14:15:22Z",
"createdBy": {
"email": "jane.doe@smartsheet.com",
"name": "Jane Doe"
}
This is what should be returning:
{
"id": 0,
"parentId": 0,
"attachmentType": "BOX_COM",
"attachmentSubType": "DOCUMENT",
"mimeType": "PNG",
"parentType": "COMMENT",
"createdAt": "2019-08-24T14:15:22Z",
"createdBy": {
"email": "jane.doe@smartsheet.com",
"name": "Jane Doe"
},
"name": "string",
"sizeInKb": 0,
"url": "string",
"urlExpiresInMillis": 0
}
Without the url attribute I'm unable to use the get_attachment method.
Any idea what I'm doing wrong? Any help is truly appreciated.
Best Answer
-
Hi @Jorge Ortiz
As stated in the API document, include expect;
A comma-separated list of optional elements to include in the response:
https://smartsheet.redoc.ly/tag/sheets#operation/getSheet
# Retrieve the sheet with attachments
sheet_id,
include=["attachments"]
)Once you get the attachment object, get attachemt_id to use the Get Attachment method to get the Attachment temporary URL (files only).
https://smartsheet.redoc.ly/tag/attachments#operation/attachments-get
Here is a sample code that downloads all the row attachments.
"Please note that this is only a demo code. You need to handle the rate limit for a sheet like yours with 5,000 rows (e.g., by adding a delay after every 300 API calls)import smartsheet
import requests
access_token = "Your access token"
smartsheet_client = smartsheet.Smartsheet(access_token)
# Set the sheet ID
sheet_id = "Your Sheet ID"
# Retrieve the sheet with attachments
sheet = smartsheet_client.Sheets.get_sheet(
sheet_id,
include=["attachments"]
)
# Create a folder to store downloaded attachments
import os
download_folder = "attachments"
if not os.path.exists(download_folder):
os.makedirs(download_folder)
print("--- Downloading Attachments ---")
# Iterate through rows in the sheet
for row in sheet.rows:
# Check if the row has attachments
if hasattr(row, 'attachments') and row.attachments:
for attachment in row.attachments:
if attachment.attachment_type == "FILE":
# Get the attachment details
attachment_id = attachment.id
file_attachment = smartsheet_client.Attachments.get_attachment(
sheet_id, # sheet_id
attachment_id # attachment_id
)
# Download the file using the URL
attachment_url = file_attachment.url
file_name = file_attachment.name
file_path = os.path.join(download_folder, file_name)
print(f"Downloading attachment: {file_name} from {attachment_url}")
# Download the file using the requests library
response = requests.get(attachment_url)
if response.status_code == 200:
with open(file_path, 'wb') as file:
file.write(response.content)
print(f"File '{file_name}' downloaded successfully to '{file_path}'.")
else:
print(f"Failed to download the file '{file_name}'. HTTP Status: {response.status_code}")
print("All attachments downloaded.")
Answers
-
Hi @Jorge Ortiz
As stated in the API document, include expect;
A comma-separated list of optional elements to include in the response:
https://smartsheet.redoc.ly/tag/sheets#operation/getSheet
# Retrieve the sheet with attachments
sheet_id,
include=["attachments"]
)Once you get the attachment object, get attachemt_id to use the Get Attachment method to get the Attachment temporary URL (files only).
https://smartsheet.redoc.ly/tag/attachments#operation/attachments-get
Here is a sample code that downloads all the row attachments.
"Please note that this is only a demo code. You need to handle the rate limit for a sheet like yours with 5,000 rows (e.g., by adding a delay after every 300 API calls)import smartsheet
import requests
access_token = "Your access token"
smartsheet_client = smartsheet.Smartsheet(access_token)
# Set the sheet ID
sheet_id = "Your Sheet ID"
# Retrieve the sheet with attachments
sheet = smartsheet_client.Sheets.get_sheet(
sheet_id,
include=["attachments"]
)
# Create a folder to store downloaded attachments
import os
download_folder = "attachments"
if not os.path.exists(download_folder):
os.makedirs(download_folder)
print("--- Downloading Attachments ---")
# Iterate through rows in the sheet
for row in sheet.rows:
# Check if the row has attachments
if hasattr(row, 'attachments') and row.attachments:
for attachment in row.attachments:
if attachment.attachment_type == "FILE":
# Get the attachment details
attachment_id = attachment.id
file_attachment = smartsheet_client.Attachments.get_attachment(
sheet_id, # sheet_id
attachment_id # attachment_id
)
# Download the file using the URL
attachment_url = file_attachment.url
file_name = file_attachment.name
file_path = os.path.join(download_folder, file_name)
print(f"Downloading attachment: {file_name} from {attachment_url}")
# Download the file using the requests library
response = requests.get(attachment_url)
if response.status_code == 200:
with open(file_path, 'wb') as file:
file.write(response.content)
print(f"File '{file_name}' downloaded successfully to '{file_path}'.")
else:
print(f"Failed to download the file '{file_name}'. HTTP Status: {response.status_code}")
print("All attachments downloaded.") -
Now I see that I was improperly using get_attachment.
Thank you so much.
-
Happy to help!😁
Categories
- All Categories
- 14 Welcome to the Community
- Customer Resources
- 65.7K Get Help
- 425 Global Discussions
- 146 Industry Talk
- 484 Announcements
- 5.1K Ideas & Feature Requests
- 86 Brandfolder
- 152 Just for fun
- 73 Community Job Board
- 494 Show & Tell
- 33 Member Spotlight
- 2 SmartStories
- 306 Events
- 37 Webinars
- 7.3K Forum Archives