Download a zip file with an ArcPY geoprocessing service in ArcGIS Portal

5124
11
Jump to solution
06-24-2020 10:28 AM
JeffHanson2
New Contributor III

I have an ExportExcelFile geoprocessing service developed in ArcPy and I want the user to get the download file URL returned so that they can click on the link and download the Excel file.   The geoprocessing service is called from a Portal Web App Geoprocessing widget.   I can get the string result but that needs to be copied and pasted into another browser tab to work.  I just want the user to click on the download URL link.   I am returning an output parameter of type "File" but only getting an object [object] in the results.   Here is the code:

import arcpy, os, json, sys, zipfile, urllib

arcpy.env.overwriteOutput = True

####################################
### setting variable default values
####################################

arcpy.env.scratchWorkspace = "//HERTZGIS/directories/arcgisoutput/PortalShapefiles/"

# Shapefile output folder
exportFolder = "//HERTZGIS/directories/arcgisoutput/PortalShapefiles/"
arcpy.AddMessage("Output folder is " + exportFolder)

#############################
### Getting input parameters
#############################

arcpy.AddMessage("  Collecting input parameters")

# Get the passed field polygon graphics and user specified shapefile name
inFeatset = arcpy.GetParameter(0)
if inFeatset == '#' or not inFeatset:
    sys.exit()

xlsFileName = arcpy.GetParameterAsText(1)
outputExcelFile = exportFolder + xlsFileName + ".xls"
if not xlsFileName:
    sys.exit()
arcpy.AddMessage("Output file is " + outputExcelFile)

#############################
### start main proccess
#############################

try:
    arcpy.AddMessage("Running shapefile export to create " + outputExcelFile)

    arcpy.TableToExcel_conversion(inFeatset, outputExcelFile)

    arcpy.AddMessage("Created shapefile: " + xlsFileName + ".xls")

    # put the files that make up the shapefile into a zip file
    zip = zipfile.ZipFile(exportFolder + xlsFileName + ".zip"'w', zipfile.ZIP_DEFLATED)
    for file in os.listdir(exportFolder):
        if file.startswith(xlsFileName):
            if not file.endswith(".zip"😞
                print(os.path.join(exportFolder, file))
                zip.write(os.path.join(exportFolder, file))
    zip.close()        
    
    vOutputFile = "https://HERTZGIS/PortalShare/" + xlsFileName + ".xls"
    aFile = open(vOutputFile)
    aFile.close()

    arcpy.AddMessage(vOutputFile)

    arcpy.SetParameter(2, aFile)
except:
    arcpy.AddMessage("Error exporting and downloading shapefile " + outputExcelFile)
1 Solution

Accepted Solutions
JeffHanson2
New Contributor III

I have solved the issue.  The GP service output should be of type "File".   The user can click a link and the zip file downloads.  The Portal arcgisjobs folder is used for the shapefile and the zip file.   Code to follow:

# ExportShapefile - Created by Jeff Hanson, HFM
# Purpose:  to export selected featues to a usernamed shapefile as a geoprocessing servie
# Note:  the output directory is PortalShapeFiles on Hertzgis server, a shared folder

import arcpy, os, json, sys, zipfile, urllib2

arcpy.env.overwriteOutput = True

####################################
### setting variable default values
####################################
arcpy.AddMessage("Default scratch GDB is:")
arcpy.AddMessage(arcpy.env.scratchGDB)
arcpy.AddMessage("*******************************")

# Excel table output folder
exportFolder = arcpy.env.scratchGDB
jobsDir = os.path.dirname(os.path.abspath(exportFolder))
arcpy.AddMessage("Export Folder: " + exportFolder)
arcpy.AddMessage("Jobs Dir: " + jobsDir)

#############################
### Getting input parameters
#############################

arcpy.AddMessage("Collecting input parameters")

# Get the passed field polygon graphics and user specified shapefile name
inFeatset = arcpy.GetParameter(0)
if inFeatset == '#' or not inFeatset:
    sys.exit()

shpFileName = arcpy.GetParameterAsText(1)
outputShapeFile = jobsDir + "\\" + shpFileName + ".shp"
if not shpFileName:
    sys.exit()
arcpy.AddMessage("Output file is " + outputShapeFile)

#############################
### start main proccess
#############################

try:
    arcpy.AddMessage("Running shapefile export to create " + outputShapeFile)

    arcpy.CopyFeatures_management(inFeatset, outputShapeFile)

    arcpy.AddMessage("Created shapefile: " + outputShapeFile)

    # put the files that make up the shapefile into a zip file
    zip = zipfile.ZipFile(jobsDir + "\\" + shpFileName + ".zip"'w', zipfile.ZIP_DEFLATED)
    for file in os.listdir(jobsDir):
        if file.startswith(shpFileName):
            if not file.endswith(".zip"😞
                print(os.path.join(jobsDir, file))
                zip.write(os.path.join(jobsDir, file))
    zip.close()    
    arcpy.AddMessage("Zip file created.")    

    outputFile = jobsDir + "\\" + shpFileName + ".zip"

    arcpy.AddMessage("Return file is " + outputFile)
    arcpy.SetParameter(2, outputFile)
except:
    arcpy.AddMessage("Error exporting and downloading shapefile " + outputShapeFile)
    sys.exit()

View solution in original post

11 Replies
DavidPike
MVP Frequent Contributor

Have you set the Parameter as Output and 'Derived'? Because you're saving to a known location, the tool doesn't have a traditional output to serve. 

0 Kudos
JeffHanson2
New Contributor III

Yes I have done that.  I am now looking at the urllib2 module.

0 Kudos
LanceKirby2
Occasional Contributor II

Maybe you should return "vOutputFile" instead of "aFile" in the SetParamter function.

0 Kudos
JeffHanson2
New Contributor III

I did try that but just get object [object] back from the geoprocessing service in Portal.   I will solve this and post the solution but it may be tomorrow.

0 Kudos
JeffHanson2
New Contributor III

I have solved the issue.  The GP service output should be of type "File".   The user can click a link and the zip file downloads.  The Portal arcgisjobs folder is used for the shapefile and the zip file.   Code to follow:

# ExportShapefile - Created by Jeff Hanson, HFM
# Purpose:  to export selected featues to a usernamed shapefile as a geoprocessing servie
# Note:  the output directory is PortalShapeFiles on Hertzgis server, a shared folder

import arcpy, os, json, sys, zipfile, urllib2

arcpy.env.overwriteOutput = True

####################################
### setting variable default values
####################################
arcpy.AddMessage("Default scratch GDB is:")
arcpy.AddMessage(arcpy.env.scratchGDB)
arcpy.AddMessage("*******************************")

# Excel table output folder
exportFolder = arcpy.env.scratchGDB
jobsDir = os.path.dirname(os.path.abspath(exportFolder))
arcpy.AddMessage("Export Folder: " + exportFolder)
arcpy.AddMessage("Jobs Dir: " + jobsDir)

#############################
### Getting input parameters
#############################

arcpy.AddMessage("Collecting input parameters")

# Get the passed field polygon graphics and user specified shapefile name
inFeatset = arcpy.GetParameter(0)
if inFeatset == '#' or not inFeatset:
    sys.exit()

shpFileName = arcpy.GetParameterAsText(1)
outputShapeFile = jobsDir + "\\" + shpFileName + ".shp"
if not shpFileName:
    sys.exit()
arcpy.AddMessage("Output file is " + outputShapeFile)

#############################
### start main proccess
#############################

try:
    arcpy.AddMessage("Running shapefile export to create " + outputShapeFile)

    arcpy.CopyFeatures_management(inFeatset, outputShapeFile)

    arcpy.AddMessage("Created shapefile: " + outputShapeFile)

    # put the files that make up the shapefile into a zip file
    zip = zipfile.ZipFile(jobsDir + "\\" + shpFileName + ".zip"'w', zipfile.ZIP_DEFLATED)
    for file in os.listdir(jobsDir):
        if file.startswith(shpFileName):
            if not file.endswith(".zip"😞
                print(os.path.join(jobsDir, file))
                zip.write(os.path.join(jobsDir, file))
    zip.close()    
    arcpy.AddMessage("Zip file created.")    

    outputFile = jobsDir + "\\" + shpFileName + ".zip"

    arcpy.AddMessage("Return file is " + outputFile)
    arcpy.SetParameter(2, outputFile)
except:
    arcpy.AddMessage("Error exporting and downloading shapefile " + outputShapeFile)
    sys.exit()
LanceKirby2
Occasional Contributor II

Glad you figured it out. I am working on a similar gp service where the user selects a layer in the first parameter and provides a string for the name in the second parameter. A shapefile and kmz are created from that layer and returned to the user. I am experiencing this issue described below.

  1. User runs gp service with LayerX selected.
    1. Everything comes back fine.
  2. They filter layerX in map and run gp service again with layerX selected in first parameter.
    1. Problem - They get back same result run from their initial run.

I'm not sure if you are doing the same workflow, but it sounds similar. If you are, can you tell me if you're running into that same issue?

0 Kudos
ShariF
by
New Contributor III

Thank you! I've done this several times and it worked but this time I forgot to change it and it stayed at the default "String".  You've saved me much frustration. 

0 Kudos
JeffHanson2
New Contributor III

I'm only returning one output file, are you returning two?  A shapefile and a KMZ?  Maybe you need 2 output parameters, one for each file type.

0 Kudos
LanceKirby2
Occasional Contributor II

That's right I am returning two files through two SetParameterAsText parameters. I have no trouble returning each file, but it's more like the call from gp widget to gp service gets stuck on the first arguments passed when using the same layer. I assume in your workflow the user could filter a layer in the attribute table, select that layer in the gp widget, and it will only export data for what was filtered. Is that correct? If so, could you run that, then go filter the same layer again and run the gp widget again? I'm curious if your data will update to reflect the filtered changes.

0 Kudos