Correct syntax for ???RESTful??? addAttachment?

4625
3
04-07-2014 07:47 PM
Highlighted
New Contributor II
Hi all,

I�??m working on a geoprocessing script that uploads a jpg from a local drive to a feature service.
I�??m having troubles getting the operation syntax right for posting the �??addAttachment�?? request to the Server.

Link to online resources:
http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Add_Attachment/02r3000000wt000000/


I�??ve tried the following:

1)  addAttachment via the ArcGIS server web browser interface (WORKING)

response:
{"addAttachmentResult":{"objectId":2001,"success":true}}


2)  I tried to replicate #1 by entering the following request into the URL bar in a web browser (NOT WORKING):

http://<my-server>/arcgis/rest/services/GeoProcessing_tools/Milling_Statement_points/FeatureServer/0/1602/addAttachment?f=json&attachment=C:\TEMP\pic00002.jpg

response:
{"error":{"code":500,"message":"java.lang.String cannot be cast to com.esri.arcgis.discovery.json.JSONObject","details":[]}}

My attachment parameter is obviously not correct. What would be the correct syntax?
The online resources�?? only info on this was:
�??The input parameter attachment to this operation is a file.�?�


3) Lastly, I tried to post the information as part of my python script using urllib (NOT WORKING):

Import urllib
url=�?? http://<my-server>/arcgis/rest/services/GeoProcessing_tools/Milling_Statement_points/FeatureServer/0/1602/addAttachment�??
payload = {'f':'json', 'attachment':{'url': r'file:///C:/TEMP/pic00002.jpg', 'contentType' : 'image/jpg'}}
response = urllib.urlopen(url, urllib.urlencode(payload)).read()
print response
{"error":{"code":500,"message":"JSONObject[\"uploadedFilePath\"] not found.","details":[]}}


Both error messages (2 & 3) include �?? �??code�?? : 500�?� which appears to point to a server-side problem.
However, the addAttachment operation works when using the web browser interface (1). Does that not contradict a server-side issue?

I�??d appreciate any help on this problem.

Cheers,
Katrin
Reply
0 Kudos
3 Replies
Highlighted
Regular Contributor III
When the documentation is insufficient to figure out how to write code I use Fiddler in order to see how ESRI does it and then try to replicate the same.

That said, the documentation you linked states the following:

"This operation adds an attachment to the associated feature (POST only). The addAttachment operation is performed on a feature service feature resource.

Since this request uploads a file, it must be a multipart request pursuant to IETF RFC1867."

I am pretty sure that this is telling you that you have to literally embed the bits from the file in the body of the POST according to the referenced standard.  I suspect that there is a Python library which provides this but I can't help you there.
Reply
0 Kudos
Highlighted
New Contributor II
Thanks for the quick response, Richard!
Both valuable pointers, thanks a lot.

Fiddler indeed revealed the multipart MIME request syntax.
I assume that's the way to go.
Reply
0 Kudos
Highlighted
New Contributor II

To complete this post, here my solution to the originally posted problem:

Import requests

url =r'http://<my-server>/arcgis/rest/services/GeoProcessing_tools/Milling_Statement_points/FeatureServer/0/1602/addAttachment'

imageRaw = r'C:/TEMP/pic00006.jpg'

imageBin = open(imageRaw, 'rb')

files = {'attachment': ('pic00006.jpg', imageBin, 'image/pjpeg')}

response = requests.post(url, files = files)

The solution was to convert the image into a binary file (thanks Richard).

The response is in html and can be parsed by using BeautifulSoup and ast for error handling:

#Parse html response

markup = BeautifulSoup(response.text)

messageRaw = markup.pre.string

message = ast.literal_eval(messageRaw.replace("true", " 'true' "))

#Confirm success

if message['addAttachmentResult']['success'] == "true":

     arcpy.AddMessage("image was successfully attached to feature")

else:

     arcpy.AddWarning("image was NOT successfully attached; server response: " + messageRaw.replace("\n", ""))

Having to replace strings and line breaks is obviously not a very clean solution.

I did not succeed in requesting the response in json format or in converting the html response into json, which would be easier to parse.

Any tips on either are still welcomed.