Hello,
Recently I needed to upload a file to a geoprocessing service using the ArcGIS JavaScript API V4 but had trouble finding a concise road map on how to achieve this. After knocking my knees on the undergrowth I am writing this blog post so you can travel the road in comfort.
I note that others have provided information for this using v3 of the API but there are some differences that this post explores relating to v4.
The Problem:
The Solution Overview:
Solution Details
Python:
There isn't anything special from the Python side of things. Simply grab the file parameter as text:
file_path = arcpy.GetParameterAsText(0)
The parameter will be a string that represents the path to the file. Once you have the path to the file you can manipulate the file as required for your purposes.
Geoprocessing Tool:
Create a geoprocessing tool in ArcMap or ArcPro with a parameter for a file with a data type of 'File'.
Matching the order of the parameter in the tool with the parameter index in the Python script is essential. If the file parameter is first in the toolbox list then this parameter has an index of zero in the Python parameter list.
This translates to the following in Python:
arcpy.GetParameterAsText(0)
Geoprocessing Service:
Run the tool in ArcMap or ArcPro so that it completes successfully.
In ArcMap, go to Geoprocessing Results, right click on the successful job and select Share As > Geoprocessing Service
In ArcPro, go to History, right click on the successful job and select Share As > Web Tool
To enable Upload capability:
Check the tool parameters are correct and add descriptions. Publish the tool, which now has the ability to upload files.
JavaScript & HTML
1. Use a document form to allow the user to nominate a file for upload:
<form enctype="multipart/form-data" method="post" id="uploadForm">
<div class="field">
<label class="file-upload">
<span><strong>Add File</strong></span>
<input type="file" name="file" id="inFile" />
</label>
</div>
</form>
2. Create a request to the geoprocessing service upload endpoint, that uses the form as the body:
document .getElementById("uploadForm") .addEventListener("change", function(event) { var fileName = event.target.value.toLowerCase(); if (fileName.indexOf(".zip") !== -1) { //is file a zip - if not notify user uploadFile(fileName); } } }); function uploadFile(fileName) { var name = fileName.split("."); // Chrome and IE add c:\fakepath to the value - we need to remove it // see this link for more info: http://davidwalsh.name/fakepath name = name[0].replace("c:\\fakepath\\", ""); var upload = esriRequest( fileUploadUrl, { body: document.getElementById("uploadForm"), method: "post", responseType: "text" //Ideally would return as json but that doesn't seem to work for me } ).then(uploadSucceeded, errBack); }
3. Handle the response of the request and extract the item ID, passing it as a parameter to the geoprocessing service:
function uploadSucceeded(result) { //Ideally the result would come back as json but as it is coming back as html it will need to be parsed for the itemid var element = document.createElement('html'); var itemID = ""; var itemURL = ""; element.innerHTML = result.data; var tdElements = element.getElementsByTagName('td'); for (let tdElement of tdElements){ if (tdElement.innerHTML == "Item ID:"){ itemID = tdElement.nextElementSibling.firstChild.innerHTML; } } if (itemID == ""){ console.log("Could not get file item id"); return } console.log("itemID: " + itemID) var params = { FileName: "{'itemID':'" + itemID + "'}" //Replaces the need for the DataFile object }; gp.submitJob(params).then(handleResult, errBack, progTest); }
Note that the JS API documentation recommends that you create a DataFile object, which you then pass as the parameter value. I could not get that to work and so constructed the object from JSON myself based on what I could see the geoprocessing service required. I determined the format of the JSON object by executing the geoprocessing service from the REST endpoint.
I have attached my full sample JS code for reference. This code not only uploads a file but also gets a response in the form of an object id of the uploaded feature. The feature is zoomed to and then a FeatureForm for that feature is opened for editing. One caveat is that at the time of writing I could not get the update button to work on the FeatureForm, probably due to an unresolved asych issue.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.