# Is it possible to use a field for the filename of an attachment export?

1047
10
06-14-2018 01:46 PM
New Contributor III

Hello,

I am able to export photo attachments with the generic script but I would like to name them based on a field on the record they are attached to. The field I would like to use is 'FID' and it's unique to each row in the table. The current code I use is.

import arcpy
from arcpy import da
import os

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

with da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'Access Point FQN_ID']) 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

1 Solution

Accepted Solutions
MVP Regular Contributor

This will get filename information from the master feature class and save an attachment in a related table.

import arcpy

masterFC = r"C:\Path\to\file.gdb\masterFC"
masterFlds = ['GlobalID', 'Name']
# Use list comprehension to build a dictionary from a da SearchCursor
masterDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(masterFC, masterFlds)}

print masterDict

relatedTbl = r'C:\Path\to\file.gdb\related_ATTACH'
relatedFlds = ['REL_GLOBALID', 'ATT_NAME', 'DATA']

fileLocation = r'C:\Path\to\attachments'

with arcpy.da.SearchCursor(relatedTbl, relatedFlds) as cursor:
for item in cursor:

# item[0] is related GlobalID; take first item in masterDict tuple with that key
f1 = masterDict[item[0]][0].replace(" ","_") # replacing spaces
# assuming attachment name starts with "attachment", remove that part and keep rest
f2 = item[1][10:] # can use .split('.')[1:] or similar to get just extension
# make new filename
filename = "ATT_{}_{}".format(f1, f2)
print filename

open(fileLocation + os.sep + filename, 'wb').write(item[2].tobytes())

del cursor‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This assumes that the master feature class contains some attributes like:

And the related attachments table is something like:

The dictionary and filenames created are:

# print masterDict

{u'{B0174984-E7EB-47EA-A49A-9D535CFD6125}': (u'State Office Building',), u'{43902175-71ED-47DB-BCC8-6C805D930D23}': (u'State Capitol',)}

# print filename

ATT_State_Capitol_1.jpg
ATT_State_Capitol_2.jpg
ATT_State_Office_Building_1.jpg‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps.

10 Replies
MVP Esteemed Contributor

/blogs/dan_patterson/2016/08/14/script-formatting would help make sure there aren't any formatting errors Craig.

Also, I don't see where you added the FID field into the searchcursor.  You will need that for your id numbers.

I presume that you haven't tested this yet?

New Contributor III

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 code is what I used. I posted the wrong code earlier.

New Contributor III

I don't know if I explained what I was trying to say earlier. I need a way to save the images and have the filename be the ID of the record they are attached to or have the filename include a field from the record they are attached too. I will give an example.

Record in table is {D40A7E01-4D12-453C-A69E-BEB4E59D9A2C}. The ID in the attachment table is df6ea7eb9fb3464f9313cae304c2b27d.

Is this possible to do this or export the relationship table?

MVP Regular Contributor

The record for the attachment should contain the global ID of the linked/master record in one of the fields.  As shown my example code, you can work it into the file name.  If the master record can have multiple attachments, you will need to use some sort of count, perhaps the attachment ID, to make a unique filename.  You will want to append a file extension which could be obtained from splitting the filename at the dot in your code or by using the data in the content type field to create an extension.

If you want to create a filename using data from the master record other than the global/linking ID field, you should be able to do that by using some sort of join with the master table or creating a dictionary of the master record feature/table.

I will work on a code sample later today or this weekend that illustrates this.

MVP Regular Contributor

I really didn't find any major problems with your script.  For testing, my script was similar:

import arcpy, os

inTable = r'C:\Path\to\file.gdb\feature__ATTACH'
fileLocation = r'C:\Path\to\attachments'

with arcpy.da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'ATTACHMENTID']) as cursor:
for item in cursor:
print "ATT_NAME: {}  - ATTACHMENTID: {}".format(item[1], item[2])
filename = "ATT_{}_{}".format(item[2], item[1])
print filename
open(fileLocation + os.sep + filename, 'wb').write(item[0].tobytes())

del cursor‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I would suggest testing with some print statements (or AddMessage), to see that  your input table and file location strings are being interpreted correctly.  For the filename, you might want to start with the attachment ID as the ATT_NAME field may include a file extension.  If it does not contain an extension, you may need to look at the CONTENT_TYPE field so your code can append one if necessary.

MVP Regular Contributor

This will get filename information from the master feature class and save an attachment in a related table.

import arcpy

masterFC = r"C:\Path\to\file.gdb\masterFC"
masterFlds = ['GlobalID', 'Name']
# Use list comprehension to build a dictionary from a da SearchCursor
masterDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(masterFC, masterFlds)}

print masterDict

relatedTbl = r'C:\Path\to\file.gdb\related_ATTACH'
relatedFlds = ['REL_GLOBALID', 'ATT_NAME', 'DATA']

fileLocation = r'C:\Path\to\attachments'

with arcpy.da.SearchCursor(relatedTbl, relatedFlds) as cursor:
for item in cursor:

# item[0] is related GlobalID; take first item in masterDict tuple with that key
f1 = masterDict[item[0]][0].replace(" ","_") # replacing spaces
# assuming attachment name starts with "attachment", remove that part and keep rest
f2 = item[1][10:] # can use .split('.')[1:] or similar to get just extension
# make new filename
filename = "ATT_{}_{}".format(f1, f2)
print filename

open(fileLocation + os.sep + filename, 'wb').write(item[2].tobytes())

del cursor‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This assumes that the master feature class contains some attributes like:

And the related attachments table is something like:

The dictionary and filenames created are:

# print masterDict

{u'{B0174984-E7EB-47EA-A49A-9D535CFD6125}': (u'State Office Building',), u'{43902175-71ED-47DB-BCC8-6C805D930D23}': (u'State Capitol',)}

# print filename

ATT_State_Capitol_1.jpg
ATT_State_Capitol_2.jpg
ATT_State_Office_Building_1.jpg‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps.

New Contributor III

Thanks Randy! That is exactly what I needed!

by Anonymous User
Not applicable

So I've been following these instructions. This is my code:

----------------------------------------------------------------------------------------------------------

import arcpy

masterFC = r"C:\Users\kameehan\OneDrive - Westwood Active Directory\Documents\Project_Documents\UI_Railroad\Shapefiles\Observations_FGDB\UI_Walkdown_Observations.gdb\Observations"
masterFlds = ['GlobalID', 'NAME']
# Use list comprehension to build a dictionary from a da SearchCursor
masterDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(masterFC, masterFlds)}

print(masterDict)

relatedTbl = r'C:\Users\kameehan\OneDrive - Westwood Active Directory\Documents\Project_Documents\UI_Railroad\Shapefiles\Observations_FGDB\UI_Walkdown_Observations.gdb\Observations_ATTACH'
relatedFlds = ['REL_GLOBALID', 'ATT_NAME', 'DATA']

fileLocation = r'C:\Users\kameehan\OneDrive - Westwood Active Directory\Documents\Project_Documents\UI_Railroad\Shapefiles\Observations_FGDB\UI_Walkdown_Observations.gdb\Observations_ATTACH'

with arcpy.da.SearchCursor(relatedTbl, relatedFlds) as cursor:
for item in cursor:

# item[0] is related GlobalID; take first item in masterDict tuple with that key
f1 = masterDict[item[0]][0].replace(" ","_") # replacing spaces
# assuming attachment name starts with "attachment", remove that part and keep rest
f2 = item[1][10:] # can use .split('.')[1:] or similar to get just extension
# make new filename
filename = "ATT_{}_{}".format(f1, f2)
print (filename)

open(fileLocation + os.sep + filename, 'wb').write(item[2].tobytes())

del cursor

---------------------------------------------------------------------------------------------------------------------------

and I keep getting this error:

Traceback (most recent call last):   File "C:\Users\kameehan\OneDrive - Westwood Active Directory\Documents\ExportAttachments2.py", line 16, in <module>     with arcpy.da.SearchCursor(relatedTbl, relatedFlds) as cursor: RuntimeError: cannot open 'C:\Users\kameehan\OneDrive - Westwood Active Directory\Documents\Project_Documents\UI_Railroad\Shapefiles\Observations_FGDB\UI_Walkdown_Observations.gdb\Observations_ATTACH'
Failed to execute (ExportAttachments2).

And I'm not sure how to fix it or what is wrong. As in why won't it open that file path?
by Anonymous User
Not applicable

rvburton Please let me know if you have any clue, or might need more information to potentially help, if you could!