http://support.esri.com/em/knowledgebase/techarticles/detail/41763
For ArcGIS 10.1+
from arcpy import da
import os
inTable = arcpy.GetParameterAsText(0)
fileLocation = arcpy.GetParameterAsText(1)
with da.SearchCursor(inTable,['DATA','ATT_NAME']) as cursor:
for row in cursor:
binaryRep = row[0]
fileName = row[1]
# save to disk
open(fileLocation + os.sep + fileName, 'wb').write(binaryRep.tobytes())
del row
del binaryRep
del fileName
You were very close! This was quite tricky actually as the ArcGIS REST API documentation didn't explain much. According to the requests docs, you can explicitly set the content headers. This worked for me:
import requests
import os
token = 'K6ZZZsf0Xtf...........PLNffN03fWcA..'
url = 'http://yourserver/arcgis/rest/services/FRLK/FS_TESTING/FeatureServer/0'
attachment = r'L:\NEWP\failed\val\PIC_00001963.pdf'
def add_attachment(url, token, oid, attachment):
att_url = '{}/{}/addAttachment'.format(url, oid)
files = {'attachment': (os.path.basename(attachment), open(attachment, 'rb'), 'application/pdf')}
params = {'token': token,'f': 'json'}
r = requests.post(att_url, params, files=files)
return r
f = add_attachment(url, token, 2402, attachment)
The real magic happens right here, which is what the REST API is looking for:
files = {'attachment': (os.path.basename(attachment), open(attachment, 'rb'), 'application/pdf')}
And the Fiddler response/webform:
Also, I have just added this functionality to my restapi repository on GitHub. You can download this and use it to perform all kinds of operations against REST Services.
If you want to go this route, you can add attachments like this:
>>> import restapi
>>> usr = 'ursername'
>>> pw = 'password'
>>> url = 'http://yourserver.com/arcgis/rest/services/Folder/Some_featureService/FeatureServer/0'
>>> pts = restapi.FeatureLayer(url, usr, pw) # only need usr and pw if using token based authentication
>>> attach = r'O:\Pfdata\New Prague\Water\MK3-R012013AFB~files\MK3_00032946.jpg'
>>> r = pts.addAttachment(802, attach) # arguments are OID and path to attachment
{u'success': True, u'objectId': 2001} #attachment has been succesfully added!
Best Answer
Here is the solution I found, I don't know if it's the best (it would be nice to capture symbology as well), but it does work and is straightforward. It's possible to grab a feature service and attachments and relationship class all in go from the server itself in a file-gdb. Esri has updated the export tools. There are now two official routes that I'm aware of for exporting feature service data with attachments.
As a normal user
Navigate to the feature service's main about page (
http://arcgis.com/home/item.html?id=xxx123456xxx
), and use the [Export] link at right side, select FGDB for output format, and you're done. (If the export link is missing, [Edit] and check the Export Data box first.)Interactively via API
Point browser to
http://services.arcgis.com/{xxx123456xxx}/arcgis/rest/services/{folder_name}/FeatureServer//createReplica
Set values to the below, unlisted items can just use default. Click on the resultant “statusURL”, and then “Result Url”, save zip file in wherever and extract a file-gdb with everything intact (except symbology).
For interest, I also found a script to this the hard way, extracting records and attachments individually and recreating locally; see AGO_PullHostedFeatures.py by Owen Evans.