Downloading Attachments through API
I have been trying to access and download attachments to rows in a Smartsheet through API using Access token. In how many ever ways, I tried to do so, that didn't work.
However, I am able to access the attachments directly that are attached to a sheet and not to a row. Are there any different permissions to access row and sheet attachments. User permission for this Smartsheet is Admin.
The error:
{'errorCode': 1006, 'message': 'Not Found', 'refId': 'p7hg71'}
Even though there are attachments, I am getting this Not Found error.
Did anyone encounter this issue before, any help here is highly appreciated.
Thank you,
Manaswitha P.
Answers
-
Here is some c# code:
PaginatedResult<Attachment> attachments = smartsheet.SheetResources.RowResources.AttachmentResources.ListAttachments(
sheetId, // sheetId
rowId, // rowId
null // PaginationParameters
);
if (attachments.TotalCount > 0)
{
for (int i = 0; i < attachments.TotalCount; i++)
{
Attachment temp = attachments.Data[i];
Attachment at = smartsheet.SheetResources.AttachmentResources.GetAttachment(
sheetId, // sheetId
(long)temp.Id // attachmentId
);
if (at.AttachmentType == AttachmentType.FILE)
{
SiteSmartsheetLinkedFileMap map = new()
{
Id = at.Id.ToString(),
URL = at.Url,
FileName = at.Name,
MimeType = at.MimeType,
RowId = rowId.ToString()
};
siteSmartSheet.RowAttachments.Add(map);
}
}
}
Regards,
Brian
-
The permissions should be the same for accessing Row and Sheet Attachments. I can confirm that I have accessed Row Attachments with Admin level permissions. I have written code using Javascript to both upload and download Attachments.
-
Hi,
Thank you for your response. Yes, I have been able to access and download the sheet and row attachments. But, after downloading, when I am trying to open the attachments, I wasn't able to.
Was getting an error as below:
Please find the code used below:
import requests
import os
# Define your Smartsheet API access token
access_token = "ACCESS_TOKEN"
# Define your Smartsheet sheet ID
sheet_id = "SHEET_ID"
# Define the endpoint for fetching sheet data
endpoint = f"https://api.smartsheet.com/2.0/sheets/sheet_id?include=attachments"
# Define headers with authorization token
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
# Send a GET request to fetch sheet data
response = requests.get(endpoint, headers=headers)
if response.status_code == 200:
rows_data = response.json()['rows']
for row in rows_data:
if 'attachments' in row:
x = row['cells'][0]['value'] # Assuming SAP Card Number is in the first column
row_id = row['id']
# Create folder for SAP Card Number
folder_name = f"Card_{x}"
# Create folder in the file system if it doesn't exist
folder_path = os.path.join("D:\\SAPMANAGER", folder_name)
if not os.path.exists(folder_path):
try:
os.makedirs(folder_path)
print(f"Folder created for SAP Card Number {x} at path: {folder_path}")
except OSError as e:
print(f"Failed to create folder for SAP Card Number {x}: {e}")
# Iterate over attachments and download/save them
attachments = row['attachments']
for attachment in attachments:
attachment_id = attachment['id']
attachment_name = attachment['name']
# Download attachment and save it to the SAP folder
attachment_url = f"https://api.smartsheet.com/2.0/sheets/sheet_id?rowid=row_id?include=attachments"
attachment_response = requests.get(attachment_url, headers=headers)
if attachment_response.status_code == 200:
attachment_content = attachment_response.content
attachment_path = os.path.join(folder_path, attachment_name)
with open(attachment_path, 'wb') as f:
f.write(attachment_content)
print(f"Attachment '{attachment_name}' downloaded and saved to folder: {folder_path}")
else:
print(f"Failed to download attachment '{attachment_name}' for SAP Card Number {x}")
else:
print("Failed to fetch sheet data")
-
This works for me to get a pdf using python3 and
requests
:import requests def download_pdf(url, save_path): response = requests.get(url) if response.status_code == 200: with open(save_path, 'wb') as f: f.write(response.content) print("PDF downloaded") else: print("Failed to download: ", response.status_code) url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" save_path = "downloaded.pdf" download_pdf(url, save_path)
Most of my code for dealing with Smartsheet Attachments was done in Javascript.
Looking at your code, I see the variable
attachment_url
to be highly suspect. You should be getting the a JSON object from Smartsheet for the specific attachment id. Here is how it is done in Javascript:const attachmentObj = await smartsheet.sheets.getAttachment({ sheetId: sheetId, attachmentId: attachmentId })
Then
attachmentObj.url
will provide a URL of the file which should look something like:https://s3.amazonaws.com/SmartsheetB1/OBJECT_ID?response-content-disposition=attachment%3Bfilename%3DMY_FILE.PDF&Signature=%2THE_SIGNATURE%3D&Expires=EXPIRES_DATETIME&AWSAccessKeyId=ACEESS_KEY_ID
So it should be a URL to an S3 object and will get you the PDF.
Hopefully, this will get you past your next hurdle
-
Hello Everyone,
I am able to download the attachments into a folder and segregating each row attachments into sub folders based on a unique column from the Smartsheet using the below Python code. Hope it should be useful for anyone who wants to work on it:
import smartsheet
import os
import requests
# Initialize Smartsheet client
smartsheet_client = smartsheet.Smartsheet('ACCESS KEY')
# Specify the sheet ID
sheet_id = 'SHEET_ID'
path = "FOLDER_PATH"
try:
# Load the sheet with include discussions and attachments
sheet = smartsheet_client.Sheets.get_sheet(sheet_id, include='attachments, discussions')
print("Loaded", len(sheet.rows), "rows from sheet:", sheet.name)
# Attachments that exist on the SHEET object
for attachment in sheet.attachments:
print("Attachment found (at SHEET-level):", attachment.name, "(attachment ID =", attachment.id, ")")
# Add logic to process attachment here.
# Attachments that exist on ROW objects
for row in sheet.rows:
for attachment in row.attachments:
# print("Attachment found (at ROW-level) on Row #", row.row_number, ":", attachment.name, "(attachment ID =", attachment.id, ")")
# Add logic to process attachment here.
print("rowid: ", row.id, ":", attachment.id, " : ", attachment.name)
response = smartsheet_client.Attachments.get_attachment(sheet_id, str(attachment.id))
# print(response)
if response.request_response.status_code == 200:
url = response.url
attachmentFile = requests.get(url)
sapCardId = row.cells[0].value #Assuming the unique column is in the first column
dir = path + f'/SAP_Card_Number_{sapCardId}'
isDirExist = os.path.exists(dir)
# remove existing directory including file(s) (tree structure)
if not isDirExist:
os.makedirs(dir)
fileName = dir + f'/{attachment.name}'
f = open(fileName, "wb")
f.write(attachmentFile.content)
f.close()
break
print("---------")
except Exception as ex:
print("Error:", ex)
Replace the access token and sheet id.. that should work :)
Thanks everyone for your suggestions.
Manaswitha.
-
Thanks for providing your solution. I will likely use it in the future.
Hint for the Future: In Smartsheet Community Discussions, you can click the paragraph symbol ¶ to the left your current typing position to format the text as
code
which will make much more readable and typically provides basic syntax highlighting.For example:
#include <stdio.h>int main() { printf("Hello world\n"); return 0; }
-
I am getting the same error again and again, how did you solve it? What was the exact issue?
-
Hi ,
I am trying to download row level attachments through API 2.0
But I am failing.Can anyone help with the process
Categories
- All Categories
- 14 Welcome to the Community
- Smartsheet Customer Resources
- 64.4K Get Help
- 424 Global Discussions
- 221 Industry Talk
- 463 Announcements
- 4.8K Ideas & Feature Requests
- 143 Brandfolder
- 144 Just for fun
- 59 Community Job Board
- 463 Show & Tell
- 32 Member Spotlight
- 1 SmartStories
- 300 Events
- 39 Webinars
- 7.3K Forum Archives