I have been searching ArcGIS for Developers and various forums to answer this question, but haven't found anything. That doesn't necessarily mean it isn't out there somewhere, I just haven't found it.
I anticipate a time when it would be nice to allow individuals to export data from a web app to shapefile, geodatabase, GeoJSON, or other formats. For instance, in both Portal and ArcGIS Online, I have an option to export a hosted feature layer to a variety of formats. Is there a widget (or even some sample code floating around out there) so that this functionality can be implemented within a JS API app?
Thanks,
Todd
Hi there,
No we do not have something out of the box. You will probably have to write your own.
The following utility converts ArcGIS JSON geometries to GeoJSON geometries and vice versa.
https://github.com/Esri/arcgis-to-geojson-utils
Hope this helps
Of course, I was hoping to hear otherwise, but this is nonetheless useful information.
Thank you.
Todd,
Have you seen the 'click and ship' or Extract Data example? It requires a geoprocessing service be set up. We just set one up to return a zip file of intersecting features.
This is great. I will look into this further and report back on my success or failure.
Glad it helped. I thought I'd share how we set it up in our app since the examples I have found are imo dated and somewhat hard to follow. So here it is, a process that takes input from the application and returns a zip file of all features that it intersects with. We kept is simple, with one input parameter and the output.
The function is fired by a button click:
<button class="btn btn-primary" on:click="getZip">Get Zip File</button>
The function:
getSiteZip () {
fileService.selected(this.$http, this.fSearch.fileSearchId).then(response => {
if (response.data && response.data.length > 0) {
var responseString = JSON.stringify(response.data)
ZipService.gpSiteZip(responseString)
}
})
}
That calls to a function in another .js file passing it the results as a JSON string. The zipdownload function initiates the download as soon as the zip file is ready.
function gpSiteZip (results) {
return new Promise((resolve, reject) => {
gp = new Geoprocessor(zipServiceUrl)
var params = {
Input_JSON_String: results
}
gp.submitJob(params, gpJobComplete, gpJobStatus, gpJobFailed).then(response => {
resolve(response)
})
})
})
}
function gpJobStatus (jobinfo) {
var jobstatus = ''
switch (jobinfo.jobStatus) {
case 'esriJobSubmitted':
jobstatus = 'Submitted...'
break
case 'esriJobExecuting':
jobstatus = 'Executing...'
break
case 'esriJobSucceeded':
jobstatus = 'Succedded...'
break
}
console.log(jobstatus)
}
function gpJobComplete (jobinfo) {
//get the Zipfile back from the service
//console.log('job complete: ', jobinfo)
gp.getResultData(jobinfo.jobId, 'GPDataFile', zipDownload)
}
function gpJobFailed (error) {
console.log(error)
}
function zipDownload (zipResult) {
var link = document.createElement('a')
link.href = zipResult.value.url
link.download = 'Download Zip'
document.body.appendChild(link)
link.click()
}
export default {
gpSiteZip: gpSiteZip
}
The service is a script tool that returns a GPDataFile.
The script's structure for creating the zip file looks like below- I took out the variables since I bet everyone who comes across this will have a different process that they can easily script. This is just to show an alternative to the ClipAndShip toolbox example.
# ------------------------------------------------------------------------------
def jsontosql(jsonstr):
# Function to parse JSON string into TRS SQL query
try:
return sqlstring
except (Exception, RuntimeError) as err:
return err
# ------------------------------------------------------------------------------
def generateAOI(sqlstring, srcFC):
# Function to generate the aoi from the sqlstring
try:
arcpy.MakeFeatureLayer_management()
arcpy.SelectLayerByAttribute_management()
aoi = arcpy.CreateUniqueName()
arcpy.CopyFeatures_management()
return aoi
except (Exception, RuntimeError) as err:
return err
# ------------------------------------------------------------------------------
def toCopy(aoi, fc_list):
# Use the aoi to select the intersecting sites
try:
featureSelected = []
for fc in fc_list:
fcname = os.path.basename(fc).split('.')[-1].replace(' ', '')
arcpy.MakeFeatureLayer_management()
arcpy.SelectLayerByLocation_management()
outfc = arcpy.CreateUniqueName()
arcpy.CopyFeatures_management()
featureInvSelected.append()
arcpy.Delete_management()
return featureSelected
except (Exception, RuntimeError) as err:
return err
# ------------------------------------------------------------------------------
def zipFolder(outFolder):
try:
# zip and return the folder
shutil.make_archive(outFolder, 'zip', outFolder)
outzip = '{}.zip'.format(outFolder)
return outzip
except (Exception, RuntimeError) as err:
return err
# ------------------------------------------------------------------------------
def getSites(instring, outputDirectory, srcFC, fc_list):
try:
# set instance specific variables
date = ''.join(datetime.now().isoformat().split('T')[0].split('-'))
outputName = 'ExtractedFeatures_' + date
# Parse instring to SQL
sqlstring = jsontosql(instring)
# generate aoi from the sqlstring
aoi = generateAOI(sqlstring, srcFC)
# generate selected sites from sql query
Selsites = toCopy(aoi, fc_list)
# Create the temporary folder with a unique name
outFolder = arcpy.CreateUniqueName(outputName, outputDirectory)
arcpy.CreateFolder_management(outputDirectory, os.path.basename(outFolder))
# Iterate over the list of selected sites and copy them to the in_memory space
for fc in Selsites:
fcount = int(arcpy.GetCount_management(fc)[0])
outfc = os.path.join(outFolder, os.path.basename(fc) + '.shp')
if fcount > 0:
arcpy.AddMessage('\t' + outfc)
arcpy.CopyFeatures_management(fc, outfc)
# Zip the folder
outzip = zipFolder(outFolder)
# Delete intermediate outputs
cleanup(aoi, siteInvSelected)
return outzip
except (Exception, RuntimeError) as err:
return err
# ------------------------------------------------------------------------------
if __name__ == '__main__':
# Scratch directory created for each jobID
outputDirectory = arcpy.env.scratchFolder
# Input parameter for selecting the sections
instring = arcpy.GetParameterAsText(0)
if instring == '#' or not instring:
# Input json object as string passed to service
instring = '[Example of the input parameter here to assist in running the tool to get a result for publishing'
# layers that will be extracted
featurelayer1 = r''
featurelayer2 = r''
featurelayer3 = r''
# featureclass used to query and select features from the other layers
featurelayer6 = r''
fc_list = [featurelayer1, featurelayer2, featurelayer3]
# Parse input JSON object string to python native list of dictionaries
instring = json.loads(instring)
# Controls the processing and returns the zipped output folder of the intersecting sites provides the output
arcpy.SetParameter(1, getSites(instring, outputDirectory, srcFC, fc_list))
Hope this helps with the process.