I'm sure this is a really elementary solution, I'm just over thinking it. I have this really simple model that takes a feature class and converts it to a GPX.

Ran the model

Then published it successfully after registering the folder where the PY code is.

When I run the GP tool from the GIS Server connection in Arc Cat, I can see that the output GPX file is going to the jobs directory, but how can I get that file? The whole point of this is to have a simple-click-one-button tool so users can get a GPX file back on their hard drive.

try:
from xml.etree import cElementTree as ET
except:
from xml.etree import ElementTree as ET
import arcpy, sys, traceback
from arcpy import env
import time, os
from subprocess import call
unicode = str
OutName = arcpy.GetParameterAsText(0)
fms = arcpy.FieldMappings()
fms.addTable("\\\\some_server\DATASTORE\GP\\PLACE FISH.sde\\FISH.DBO.FISH_BARRIERS")
FLD_STATION_NAME = arcpy.FieldMap()
FLD_STREAMNAME = arcpy.FieldMap()
FLD_EDITDATE = arcpy.FieldMap()
FLD_STATION_NAME.addInputField("\\\\some_server\DATASTORE\GP\\PLACE FISH.sde\\FISH.DBO.FISH_BARRIERS", "STATION_NAME")
STATION_NAME_MAP = FLD_STATION_NAME.outputField
STATION_NAME_MAP.name = "Name"
FLD_STATION_NAME.outputField = STATION_NAME_MAP
fms.addFieldMap(FLD_STATION_NAME)
FLD_STREAMNAME.addInputField("\\\\some_server\DATASTORE\GP\\PLACE FISH.sde\\FISH.DBO.FISH_BARRIERS", "STREAMNAME")
STREAMNAME_MAP = FLD_STREAMNAME.outputField
STREAMNAME_MAP.name = "Descript"
FLD_STREAMNAME.outputField = STREAMNAME_MAP
fms.addFieldMap(FLD_STREAMNAME)
FLD_EDITDATE.addInputField("\\\\some_server\DATASTORE\GP\\PLACE FISH.sde\\FISH.DBO.FISH_BARRIERS", "EDITDATE")
EDITDATE_MAP = FLD_EDITDATE.outputField
EDITDATE_MAP.name = "DateTimeS"
EDITDATE_MAP.type = "Text"
FLD_EDITDATE.outputField = EDITDATE_MAP
fms.addFieldMap(FLD_EDITDATE)
arcpy.FeatureClassToFeatureClass_conversion("\\\\some_server\DATASTORE\GP\\PLACE FISH.sde\\FISH.DBO.FISH_BARRIERS", "\\\\some_server\DATASTORE\GP\\", "FISH_BARRIERS.shp", "", fms)
gpx = ET.Element("gpx", xmlns="http://www.topografix.com/GPX/1/1",
xalan="http://xml.apache.org/xalan",
xsi="http://www.w3.org/2001/XMLSchema-instance",
creator="Esri",
version="1.1")
def prettify(elem):
"""Return a pretty-printed XML string for the Element.
"""
from xml.dom import minidom
rough_string = ET.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
def featuresToGPX(inputFC, outGPX, zerodate, pretty):
''' This is called by the __main__ if run from a tool or at the command line
'''
descInput = arcpy.Describe(inputFC)
if descInput.spatialReference.factoryCode != 4326:
arcpy.AddWarning("Input data is not projected in WGS84,"
" features were reprojected on the fly to create the GPX.")
generatePointsFromFeatures(inputFC , descInput, zerodate)
# Write the output GPX file
try:
if pretty:
gpxFile = open(outGPX, "w")
gpxFile.write(prettify(gpx))
else:
gpxFile = open(outGPX, "wb")
ET.ElementTree(gpx).write(gpxFile, encoding="UTF-8", xml_declaration=True)
except TypeError as e:
arcpy.AddError("Error serializing GPX into the file.")
finally:
gpxFile.close()
def generatePointsFromFeatures(inputFC, descInput, zerodate=False):
def attHelper(row):
# helper function to get/set field attributes for output gpx file
pnt = row[1].getPart()
valuesDict["PNTX"] = str(pnt.X)
valuesDict["PNTY"] = str(pnt.Y)
Z = pnt.Z if descInput.hasZ else None
if Z or ("ELEVATION" in cursorFields):
valuesDict["ELEVATION"] = str(Z) if Z else str(row[fieldNameDict["ELEVATION"]])
else:
valuesDict["ELEVATION"] = str(0)
valuesDict["NAME"] = row[fieldNameDict["NAME"]] if "NAME" in fields else " "
valuesDict["DESCRIPT"] = row[fieldNameDict["DESCRIPT"]] if "DESCRIPT" in fields else " "
if "DATETIMES" in fields:
row_time = row[fieldNameDict["DATETIMES"]]
formatted_time = row_time if row_time else " "
elif zerodate and "DATETIMES" not in fields:
formatted_time = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(0))
else:
formatted_time = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(0)) if zerodate else " "
valuesDict["DATETIMES"] = formatted_time
return
#-------------end helper function-----------------
def getValuesFromFC(inputFC, cursorFields ):
previousPartNum = 0
startTrack = True
# Loop through all features and parts
with arcpy.da.SearchCursor(inputFC, cursorFields, spatial_reference="4326", explode_to_points=True) as searchCur:
for row in searchCur:
if descInput.shapeType == "Polyline":
for part in row:
newPart = False
if not row[0] == previousPartNum or startTrack is True:
startTrack = False
newPart = True
previousPartNum = row[0]
attHelper(row)
yield "trk", newPart
elif descInput.shapeType == "Multipoint" or descInput.shapeType == "Point":
# check to see if data was original GPX with "Type" of "TRKPT" or "WPT"
trkType = row[fieldNameDict["TYPE"]].upper() if "TYPE" in fields else None
attHelper(row)
if trkType == "TRKPT":
newPart = False
if previousPartNum == 0:
newPart = True
previousPartNum = 1
yield "trk", newPart
else:
yield "wpt", None
# ---------end get values function-------------
# Get list of available fields
fields = [f.name.upper() for f in arcpy.ListFields(inputFC)]
valuesDict = {"ELEVATION": 0, "NAME": "", "DESCRIPT": "", "DATETIMES": "", "TYPE": "", "PNTX": 0, "PNTY": 0}
fieldNameDict = {"ELEVATION": 0, "NAME": 1, "DESCRIPT": 2, "DATETIMES": 3, "TYPE": 4, "PNTX": 5, "PNTY": 6}
cursorFields = ["OID@", "SHAPE@"]
for key, item in valuesDict.items():
if key in fields:
fieldNameDict[key] = len(cursorFields) # assign current index
cursorFields.append(key) # build up list of fields for cursor
else:
fieldNameDict[key] = None
for index, gpxValues in enumerate(getValuesFromFC(inputFC, cursorFields)):
if gpxValues[0] == "wpt":
wpt = ET.SubElement(gpx, 'wpt', {'lon':valuesDict["PNTX"], 'lat':valuesDict["PNTY"]})
wptEle = ET.SubElement(wpt, "ele")
wptEle.text = valuesDict["ELEVATION"]
wptTime = ET.SubElement(wpt, "time")
wptTime.text = valuesDict["DATETIMES"]
wptName = ET.SubElement(wpt, "name")
wptName.text = valuesDict["NAME"]
wptDesc = ET.SubElement(wpt, "desc")
wptDesc.text = valuesDict["DESCRIPT"]
else: #TRKS
if gpxValues[1]:
# Elements for the start of a new track
trk = ET.SubElement(gpx, "trk")
trkName = ET.SubElement(trk, "name")
trkName.text = valuesDict["NAME"]
trkDesc = ET.SubElement(trk, "desc")
trkDesc.text = valuesDict["DESCRIPT"]
trkSeg = ET.SubElement(trk, "trkseg")
trkPt = ET.SubElement(trkSeg, "trkpt", {'lon':valuesDict["PNTX"], 'lat':valuesDict["PNTY"]})
trkPtEle = ET.SubElement(trkPt, "ele")
trkPtEle.text = valuesDict["ELEVATION"]
trkPtTime = ET.SubElement(trkPt, "time")
trkPtTime.text = valuesDict["DATETIMES"]
if __name__ == "__main__":
''' Gather tool inputs and pass them to featuresToGPX
'''
inputFC = "\\\\some_server\DATASTORE\GP\\FISH_BARRIERS.shp"
outGPX = OutName
zerodate = "#"
pretty = "#"
featuresToGPX(inputFC, outGPX, zerodate, pretty)
arcpy.Delete_management("\\\\some_server\DATASTORE\GP\\FISH_BARRIERS.shp")
Solved! Go to Solution.
This worked for me when using data drive pages.
output = targetJobname + ".pdf"
Output_File = os.path.join(arcpy.env.scratchFolder, output)
ddp.exportToPDF(Output_File, "CURRENT")
#forgot to add
arcpy.SetParameterAsText(1, Output_File)
This worked for me when using data drive pages.
output = targetJobname + ".pdf"
Output_File = os.path.join(arcpy.env.scratchFolder, output)
ddp.exportToPDF(Output_File, "CURRENT")
#forgot to add
arcpy.SetParameterAsText(1, Output_File)
Thanks. Based on https://community.esri.com/thread/104530#comment-388705 , Custom Geoprocessing Tool Reporting for ArcGIS online , Geoprocessing Service Output File scratch directory path to url , and Geoprocessing Service Output Directory that seems to be the path. But I'm having a hard time figuring out how to a) replicate your example in my specific situation, and b) how to present the file to the user. Where this is all leading to, I'm hoping to embed the GP service in the GP Widget in WAB, with similar functionality as how Tutorial: Publishing additional services for printing—Documentation | ArcGIS for Server works in WAB: delivering a click-to-download pdf. In this case, I need a click-to-download gpx file. But first I have to figure out how to make the underlying logic work. Thanks!
So I've modified the PY as such:
inputFC = "\\\\server\DATASTORE\GP\\FISH_BARRIERS.shp"
outGPX = os.path.join(arcpy.env.scratchFolder, OutName)
zerodate = "#"
pretty = "#"
featuresToGPX(inputFC, outGPX, zerodate, pretty)
arcpy.Delete_management("\\\\server\DATASTORE\GP\\FISH_BARRIERS.shp")
Re-ran the tool, republished it, same result:

Added it to a WAB (developer) GP Widget

Hit execute, same result: nothing.
Am I missing something elementary-obvious or does this workflow only work with the export-web-map-to-pdf task example?
Update...implementing some of your answer, setting the job to asych, and setting "add to display" in the model solved this. You can infer I spent ALL WEEKEND ON THIS.....

Once I polish up the workflow I'll document it in a blog.
Opps looks like I missed this last line in my copy and paste which may do it. Really sorry about that.
arcpy.SetParameterAsText(1, Output_File)