Please help with batch exporting photo attachments in Field Maps

09-04-2022 05:27 PM
New Contributor

I would like to batch export my photo attachments from Field Maps on my local network. I need an efficient way to have multiples photos that are associated with a single survey be named in a way that lets me know what survey they're tied to. I have discovered a couple of scripts for ArcGIS Collector that batch export the attachments to my local folder, but the script only address one attachment per survey. I believe this happens because the script is written in a way that it assumes the attachment table is a one-to-one with the feature layer. I typically have a couple of photos per record and my surveys entail hundreds of records. I am able to get the first attachment exported with appropriate names but the script ignores a second or a third attachment for the same record. Would anyone be able to help me with a complete script that exports all photo attachments for each record? 

This is the script that I have been using:

# imports the necessary modules to run
from arcpy import da
import os

attachTable = arcpy.GetParameterAsText(0) # table in GDB holding attachments
origTable = arcpy.GetParameterAsText(1) # layer in GDB holding features to which attachments belong
nameField = arcpy.GetParameterAsText(2) # field in origTable that contains more appropriate name for attachment
fileLocation = arcpy.GetParameterAsText(3) # folder where you want to save the photos

# create the cursor to search through the attachment tables; specify you only wish to search those three fields
attachCursor = da.SearchCursor(attachTable,['DATA','ATT_NAME','REL_GLOBALID'])

# begin searching the table and storing the actual images, movies, etc
for attRow in attachCursor:
binaryRep = attRow[0]
fileName = attRow[1]
relID = attRow[2] # defines the relationship ID that we can use to join to the actual features (origTable)

# creates a cursor to sort the features; essentially to find a match for the relID above
originCursor = da.SearchCursor(origTable,['GlobalID', nameField])
for origRow in originCursor:
origID = origRow[0] # store the Global ID (which will match to the relID above for the correct attachment)
origName = origRow[1] # store the unique name of each record that you will use to save the attachment
if origID == relID: # stops the search after it finds the record which equals the ID from the attachments

# saves a file in the specified location that contains the name chosen by the user for that attachment
open(fileLocation + os.sep + origName + ".jpg",'wb').write(binaryRep.tobytes())

# iteratively deletes the searchCursor from the feature class so it can reboot for the next attachment!
del originCursor

# If you are creating script from Sratch in ArcGIS
# Parameter(0) Type = Table
# Parameter(1) Type = Feature Layer
# Parameter(2) Type = Field (obtained from Parameter(1)
# Parameter(3) Type = Folder (make sure it is an input)

0 Kudos
1 Reply
MVP Esteemed Contributor

Looks like your code keeps naming all the photos the same name this will overwrite it each time so you just get 1.  In 123 I have a field that calcs my photo name for me then I use that.  You could add a field with Arcade to do that or you could just have the script query the output dir and get the number of files then add 1 and append that to you export name.  (assuming not other stuff in the folder)

Something like (I did not check syntax but you get the idea).

numberToUse = count(os.listdir(fileLocation)) + 1

open(fileLocation + os.sep + origName + str(numberToUse) + ".jpg",'wb').write(binaryRep.tobytes())

Hope that helps

My script is here

I then create HTML pages in the dir with this


0 Kudos