Select to view content in your preferred language

Export Attachments from Feature Class

1162
8
01-31-2023 01:32 PM
by Anonymous User
Not applicable

I have a feature class that has several attachments stored in related tables. I've been trying to use this Export Attachments script to store the attachments in a local folder, but things aren't working right.

import arcpy
from arcpy import da
import os

inTable = arcpy.GetParameterAsText(0)
fileLocation = arcpy.GetParameterAsText(1)

with da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'ATTACHMENTID']) as cursor:
    for item in cursor:
        attachment = item[0]
        filenum = "ATT" + str(item[2]) + "_"
        filename = filenum + str(item[1])
        open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes())
        del item
        del filenum
        del filename
        del attachment

The tool runs successfully with no errors or warnings. My output location remains empty though. I was thinking that it might just be an indexing issue. This is my attachment table.

JeremyBarnby1_0-1675200252730.png

I've ran the script as is, and I've also ran it by indexing "filenum" to [0] and "filename" to [4], the ATT_NAME field. I've verified that there are actually attachments in the related table. Does anyone know what I could be doing wrong here? Thanks.

EDIT: I just realized that the input and output just indices to the inputs in the tool. Here's what the tool looks like. Running a script like above without putting anything into the tool won't work...unless I hardcode the parameters (having trouble with that too!).

JeremyBarnby1_0-1675434622337.png

 

0 Kudos
8 Replies
RhettZufelt
MVP Notable Contributor

Seems to be working just fine for me as is.

Might be something to do with your path/locations.  You could try hard coding the paths and see if that resolves the issue.  Then, at least you know where it is going wrong.

Also, make sure you are pointing the search cursor at the attachment table and not the feature class.

 

fileLocation = r'C:\tmp\Attachments'                       # folder where attachments are saved
inTable = r'Database Connections\SignsDatabase.sde\SignsDatabase.DBO.Signs__ATTACH'   #  attachment table for feature class

 

Also, can't see the full ATT_NAME in your table, but looks like it could be long with multiple characters.

Want to make sure the final path/filename are still valid filenames within windows.

R_

0 Kudos
by Anonymous User
Not applicable

I've hard coded the paths in there with raw string file paths, and now I'm getting a runtime error saying that it can't open my attachment table.

Traceback (most recent call last):
File "C:/Users/UserName/Documents/Projects/Scripts/ExportAttachments.py", line 11, in <module>
with da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'ATTACHMENTID']) as cursor:
RuntimeError: cannot open 'C:\Users\UserName\Documents\Projects\MI Green Schools Export\5b060c49-050b-40fa-938b-542ca0ec171b.gdb'

0 Kudos
by Anonymous User
Not applicable

Does your ATT_NAME include the file extension at the end?

0 Kudos
by Anonymous User
Not applicable

Yeah, all the ATT_NAMEs have extensions at the end. There is one attachment table that's empty, but I haven't been able to get the code to extract the files even on the tables that actually have attachments.

 

0 Kudos
RhettZufelt
MVP Notable Contributor

If you put some print statements in there, what is is saying for:

print inTable
print fileLocation + os.sep + filename

R_

0 Kudos
by Anonymous User
Not applicable

Printing the inTable points to the .gdb of the attachment table. I can't print the filename because it's nested within the for loop and the code needs to access the attachment table in order for the filename to be generated. 

0 Kudos
RhettZufelt
MVP Notable Contributor

I only see that error when inTable is set to the FGDB and not to the attachment table itself.

Does adding the path to the actual attachment table make a difference?

print inTable right before the cursor would show you what it is actually using.

inTable = r'C:\Users\UserName\Documents\Projects\MI Green Schools Export\5b060c49-050b-40fa-938b-542ca0ec171b.gdb\tablename__ATTACH'

Don't think it would make a difference with anything here put the print statements, but are you running python 2.7 or 3.x?

R_

0 Kudos
RhettZufelt
MVP Notable Contributor

Python 2 or 3?

Sounds like all you need to do is update inTable to point to the actually attachments table (Not the .gdb) and should be good to go.

import arcpy
from arcpy import da
import os

inTable = arcpy.GetParameterAsText(0)
fileLocation = arcpy.GetParameterAsText(1)

print inTable    #  for python 2.7
print(inTable)   # for python 3

with da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'ATTACHMENTID']) as cursor:
    for item in cursor:
        attachment = item[0]
        filenum = "ATT" + str(item[2]) + "_"
        filename = filenum + str(item[1])

        print fileLocation + os.sep + filename  # python 2.7
        print(fileLocation + os.sep + filename)  # python 3

        open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes())
        del item
        del filenum
        del filename
        del attachment

If not, you can add print statements to the code as above. This will have access to the variable within the loop.

R_

0 Kudos