Re-Import images into an attachment table

628
4
Jump to solution
09-22-2022 12:42 PM
GustafsonTerry
New Contributor II

Not sure if this is the right area to post this question but here goes.  I have created a script to export images from an attachment table in Oracle to a local file share.  I then have date stamped those images.  I'm wondering if its possible to re-import those images back into the Oracle table.  When the images are first exported they are named like this 

"00013EB_JPG_OID{BA212223-344F-4BE8-BA6F-0DA12BF8F1CE}.JPG"

So the file is named with the REL_GLOBALID.

Just curious if anyone has done anything like this?

Thanks for your time.

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable

One to Many... I think you can use the current match table in the searchcursor instead of the fc and create the list of dictionaries from it so you get the multiple fc objectid to unique attachment. Then reverse the lookup to the jpg dictionary to get the jpg info.  This untested, but where I would start at.

 

from os import listdir
from os.path import isfile, join
import csv
import arcpy

jpgDir = r'path to folder holding the jpgs'
fc = r'path to the fc'
mtchTble = r'path to match table'

# create a dictionary of jpeg files.
jpgfiles = {f: {'fileJPG': f.split('.')[0], 'fileJpgName': f, 'jpgPath': join(jpgDir, f)} for f in listdir(jpgDir) if all([isfile(join(jpgDir, f)), f.endswith('jpg')])}

# Create the empty list to hold the dictionaries from the Search Cursor
data_dict_list = []

# Iterate over the match table and link the REL_GLOBALID to the jpg file info that we created earlier. Create a dictionary of the values and add it to the list.
with arcpy.da.SearchCursor(mtchTble, ['OBJECTID', 'fc_match_field', 'REL_GLOBALID']) as sCur:
    for row in sCur:
        # get the matching jpg, or default to an empty dict.
        jpgMatch = jpgfiles.get(row[2])
        if jpgMatch: # <- build the dict if it exists in the jpg dictionary
            # combine the values from the current match table and jpg file data into a dictionary and append it to the list
            tmpDict = {'OBJECTID': row[1], 'fc_match_field': row[1], 'REL_GLOBALID': row[2], 'fileJPG': jpgMatch['fileJPG'], 'fileJpgName': jpgMatch['fileJpgName'], 'jpgPath': jpgMatch['jpgPath']}
            data_dict_list.append(tmpDict)

# fields to use as the csv header
csv_header = ['ObjectID', 'fileJPG', 'fileJpgName', 'jpgPath', 'REL_GLOBALID']

# write the csv
with open(r'match.csv', 'w', newline="") as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=csv_header)
    writer.writeheader()
    for data in data_dict_list:
        writer.writerow(data)

# remove and add the updated attachments
arcpy.RemoveAttachments_management(fc, 'OBJECTID', 'match.csv', 'OBJECTID', 'fileJpgName')

arcpy.management.AddAttachments(fc, 'OBJECTID', 'match.csv', 'fc_match_field', 'jpgPath')

 

View solution in original post

4 Replies
EarlMedina
Esri Regular Contributor

I have done this, but on the Feature Service side (for which I made use of the ArcGIS API for Python). In my case, I was re-attaching files on a Hosted Feature service so that was the most feasible option.

 

You've probably already seen this, but to do it locally you would use this function: Add Attachments (Data Management)—ArcGIS Pro | Documentation

So, you'd need a match table seems like - I'm guessing you could programmatically create a csv with summary information on the directory containing the images, create a TableView from that, and that would basically get you most of the way there.

by Anonymous User
Not applicable

I created and posted this on another post from a few weeks ago but it also applies to your question.

This will create the attachement csv, matching the on the REL_GLOBALID. You may need to parse out the GUID from the file name but it should get you started.

 

from os import listdir
from os.path import isfile, join
import csv
import arcpy

jpgDir = r'path to folder holding the jpgs'
fc = r'path to the fc'

# create a dictionary of jpeg files.
jpgfiles = {f: {'fileJPG': f.split('.')[0], 'fileJpgName': f, 'jpgPath': join(jpgDir, f)} for f in listdir(jpgDir) if all([isfile(join(jpgDir, f)), f.endswith('jpg')])}

# add the matching REL_GLOBALID from the featureclass:
# make list of jpeg names for the sql query.
jpgs = [k for k in jpgfiles.keys()]

sql = f"""REL_GLOBALID IN ({str(jpgs)[1:-1]})"""
# limit the results to the jpegs in the folder and add the objectID/rel_Globalid to the dictionary.
with arcpy.da.SearchCursor(fc, ['OBJECTID', 'REL_GLOBALID'], sql) as sCur:
    for row in sCur:
        jpgfiles[row[1]]['ObjectID'] = row[0]
        jpgfiles[row[1]]['REL_GLOBALID'] = row[1]

# convert the jpeg file dict to a list of dicts containing the matched objectid and jpeg data.
dict_data = [dict(v.items()) for k, v in jpgfiles.items()]

# fields to use as the csv header
csv_header = ['ObjectID', 'fileJPG', 'fileJpgName', 'jpgPath', 'REL_GLOBALID']
# write the csv
with open(r'match.csv', 'w', newline="") as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=csv_header)
    writer.writeheader()
    for data in dict_data:
        writer.writerow(data)

# remove and add the updated attachments
arcpy.RemoveAttachments_management(fc, 'OBJECTID', 'match.csv', 'OBJECTID', 'fileJpgName')

arcpy.management.AddAttachments(fc, 'OBJECTID', 'match.csv', 'OBJECTID', 'jpgPath')

 

 

0 Kudos
GustafsonTerry
New Contributor II

I'm new to Py so will this work if I have several images associated with one feature?  I have features that have several images tied to to them with the same rel_globalid but different att_name?   Or is the OBJECTID used the match the different files?

 

Thank you!

0 Kudos
by Anonymous User
Not applicable

One to Many... I think you can use the current match table in the searchcursor instead of the fc and create the list of dictionaries from it so you get the multiple fc objectid to unique attachment. Then reverse the lookup to the jpg dictionary to get the jpg info.  This untested, but where I would start at.

 

from os import listdir
from os.path import isfile, join
import csv
import arcpy

jpgDir = r'path to folder holding the jpgs'
fc = r'path to the fc'
mtchTble = r'path to match table'

# create a dictionary of jpeg files.
jpgfiles = {f: {'fileJPG': f.split('.')[0], 'fileJpgName': f, 'jpgPath': join(jpgDir, f)} for f in listdir(jpgDir) if all([isfile(join(jpgDir, f)), f.endswith('jpg')])}

# Create the empty list to hold the dictionaries from the Search Cursor
data_dict_list = []

# Iterate over the match table and link the REL_GLOBALID to the jpg file info that we created earlier. Create a dictionary of the values and add it to the list.
with arcpy.da.SearchCursor(mtchTble, ['OBJECTID', 'fc_match_field', 'REL_GLOBALID']) as sCur:
    for row in sCur:
        # get the matching jpg, or default to an empty dict.
        jpgMatch = jpgfiles.get(row[2])
        if jpgMatch: # <- build the dict if it exists in the jpg dictionary
            # combine the values from the current match table and jpg file data into a dictionary and append it to the list
            tmpDict = {'OBJECTID': row[1], 'fc_match_field': row[1], 'REL_GLOBALID': row[2], 'fileJPG': jpgMatch['fileJPG'], 'fileJpgName': jpgMatch['fileJpgName'], 'jpgPath': jpgMatch['jpgPath']}
            data_dict_list.append(tmpDict)

# fields to use as the csv header
csv_header = ['ObjectID', 'fileJPG', 'fileJpgName', 'jpgPath', 'REL_GLOBALID']

# write the csv
with open(r'match.csv', 'w', newline="") as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=csv_header)
    writer.writeheader()
    for data in data_dict_list:
        writer.writerow(data)

# remove and add the updated attachments
arcpy.RemoveAttachments_management(fc, 'OBJECTID', 'match.csv', 'OBJECTID', 'fileJpgName')

arcpy.management.AddAttachments(fc, 'OBJECTID', 'match.csv', 'fc_match_field', 'jpgPath')