We ran into this and if you are comfortable with some python then this will work. It will bring everything down to your FGDB and create folders named by GUID with the appropriate JPEG's extracted inside of them.
Here are the instructions for the python tool:
1) Create local file geodatabase to hold data and attachments you want to download from ArcGIS Online (called data.gdb in script)
2) Create feature class (called myLayer in script), enable attachments, add globalID's
3) Add the following field to the feature class -GlobalID_str, text, length: 50
4) Create table called MatchTable (called MatchTable in script).
5) Add the following fields to the MatchTable table:
- GlobalID_Str, text, length: 50
- PhotoPath, text length: 255
6) Enable "sync" on hosted feature service (http://resources.arcgis.com/en/help/arcgisonline/index.html#//010q000000n0000000)
7) Open AGOL_pullFeatures script in text editor and modify the following:
-ArcGIS Online username/password
-REST url to feature service to pull from
-path to and name of local file geodatabase
-fields to pull from the hosted feature service (must match local feature class)
-name of local feature class (this will hold the data from the hosted service and the attachments)
import os, urllib, urllib2, datetime, arcpy, json
def updateValue(row,field_to_update,value):
outputfield=next((f for f in fields if f.name ==field_to_update),None)
if outputfield == None or value == None:
return
if outputfield.type == 'Date':
if value > 0 :
value = datetime.datetime.fromtimestamp(value/1000)
row.setValue(field_to_update,value)
else:
row.setValue(field_to_update,value)
return
gtUrl = 'https://www.arcgis.com/sharing/rest/generateToken'
gtValues = {'username' : 'XXX',
'password' : 'XXX',
'referer' : 'http://www.arcgis.com',
'f' : 'json' }
gtData = urllib.urlencode(gtValues)
gtRequest = urllib2.Request(gtUrl, gtData)
gtResponse = urllib2.urlopen(gtRequest)
gtJson = json.load(gtResponse)
token = gtJson['token']
crUrl = 'http://services1.arcgis.com/XXX/arcgis/rest/services/FeatureLayerName/FeatureServer/CreateReplica'
crValues = {'f' : 'json',
'layers' : '0',
'returnAttachments' : 'true',
'token' : token }
crData = urllib.urlencode(crValues)
crRequest = urllib2.Request(crUrl, crData)
crResponse = urllib2.urlopen(crRequest)
crJson = json.load(crResponse)
replicaUrl = crJson['URL']
urllib.urlretrieve(replicaUrl, 'myLayer.json')
cwd = os.getcwd()
with open('myLayer.json') as data_file:
data = json.load(data_file)
for x in data['layers'][0]['attachments']:
gaUrl = x['url']
gaFolder = cwd + '\\photos\\' + x['parentGlobalId']
if not os.path.exists(gaFolder):
os.makedirs(gaFolder)
gaName = x['name']
gaValues = {'token' : token }
gaData = urllib.urlencode(gaValues)
urllib.urlretrieve(url=gaUrl + '/' + gaName, filename=os.path.join(gaFolder, gaName),data=gaData)
rows = arcpy.InsertCursor(cwd + '/data.gdb/myLayer')
fields = arcpy.ListFields(cwd + '/data.gdb/myLayer')
for cfX in data['layers'][0]['features']:
pnt = arcpy.Point()
pnt.X = cfX['geometry']['x']
pnt.Y = cfX['geometry']['y']
row = rows.newRow()
row.shape = pnt
updateValue(row,'OBJECTID', cfX['attributes']['OBJECTID'])
updateValue(row,'Route_Code', cfX['attributes']['Route_Code'])
updateValue(row,'Primary_Route', cfX['attributes']['Primary_Route'])
updateValue(row,'Street_Name', cfX['attributes']['Street_Name'])
updateValue(row,'Structure_Type', cfX['attributes']['Structure_Type'])
updateValue(row,'Pole_Designation_Number', cfX['attributes']['Pole_Designation_Number'])
updateValue(row,'Visible_Cracks', cfX['attributes']['Visible_Cracks'])
updateValue(row,'Number_Of_Cracks', cfX['attributes']['Number_Of_Cracks'])
updateValue(row,'Longest_Crack_Length', cfX['attributes']['Longest_Crack_Length'])
updateValue(row,'Pole_Multi_Sided', cfX['attributes']['Pole_Multi_Sided'])
updateValue(row,'Number_Of_Sides', cfX['attributes']['Number_Of_Sides'])
updateValue(row,'Number_Of_Anchor_Bolts', cfX['attributes']['Number_Of_Anchor_Bolts'])
updateValue(row,'Anchor_Bolt_Cracked', cfX['attributes']['Anchor_Bolt_Cracked'])
updateValue(row,'Nuts_Loose', cfX['attributes']['Nuts_Loose'])
updateValue(row,'Lock_Washers_OK', cfX['attributes']['Lock_Washers_OKs'])
updateValue(row,'FollowUp_Status', cfX['attributes']['FollowUp_Status'])
updateValue(row,'FollowUp_Comments ', cfX['attributes']['FollowUp_Comments '])
updateValue(row,'FollowUp_Complete', cfX['attributes']['FollowUp_Complete'])
updateValue(row,'District', cfX['attributes']['District'])
updateValue(row,'County', cfX['attributes']['County'])
updateValue(row,'Latitude', cfX['attributes']['Latitude'])
updateValue(row,'Longitude', cfX['attributes']['Longitude'])
updateValue(row,'NLFID', cfX['attributes']['NLFID'])
updateValue(row,'GlobalID', cfX['attributes']['GlobalID'])
updateValue(row,'NLFID', cfX['attributes']['NLFID'])
updateValue(row,'CreationDate', cfX['attributes']['CreationDate'])
updateValue(row,'Creator', cfX['attributes']['Creator'])
updateValue(row,'EditDate', cfX['attributes']['EditDate'])
updateValue(row,'Editor', cfX['attributes']['Editor'])
updateValue(row,'GlobalID_str', cfX['attributes']['GlobalID'])
rows.insertRow(row)
del row
del rows
rows = arcpy.InsertCursor(cwd + '/data.gdb/MatchTable')
for cmtX in data['layers'][0]['attachments']:
row = rows.newRow()
row.setValue('GlobalID_Str', cmtX['parentGlobalId'])
row.setValue('PhotoPath', cwd + '\\photos\\' + cmtX['parentGlobalId'] + '\\' + cmtX['name'])
rows.insertRow(row)
del row
del rows
arcpy.AddAttachments_management(cwd + '/data.gdb/myLayer', 'GlobalID_Str', cwd + '/data.gdb/MatchTable', 'GlobalID_Str', 'PhotoPath')