ArcGIS REST API: Generate

3716
16
Jump to solution
04-23-2018 11:37 AM
JamesCrandall
MVP Frequent Contributor

I'm not sure what to do as I don't see any error and dev tools doesn't report anything.  I'm attempting to implement this Add Shapefile sample into a button click on a new custom widget.  The issue seems to be happening in setting up the "request"

        generateFeatureCollection: function (fileName) {
            var name1 = 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
            var name = name1[0].replace("c:\\fakepath\\", "");
            console.log("processing filename: ", name)
            //dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;

            //Define the input params for generate see the rest doc for details
            //http://www.arcgis.com/apidocs/rest/index.html?generate.html
            var params = {
                'name': name,
                'targetSR': map.spatialReference,
                'maxRecordCount': 1000,
                'enforceInputFileSizeLimit': true,
                'enforceOutputJsonSizeLimit': true
            };
            console.log("params: ", params)

            //generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
            //This should work well when using web mercator.
            var extent = scaleUtils.getExtentForScale(map, 40000);
            var resolution = extent.getWidth() / map.width;
            params.generalize = true;
            params.maxAllowableOffset = resolution;
            params.reducePrecision = true;
            params.numberOfDigitsAfterDecimal = 0;

            var myContent = {
                'filetype': 'shapefile',
                'publishParameters': JSON.stringify(params),
                'f': 'json',
                'callback.html': 'textarea'
            };
            console.log("myContent: ", myContent)
            console.log("setting up request")
            //use the rest generate operation to generate a feature collection from the zipped shapefile
            request({
                url: portalUrl + '/sharing/rest/content/features/generate',
                content: myContent,
                form: lang.hitch(this, dom.byId('uploadForm')),
                form: dom.byId('uploadForm'),
                handleAs: 'json',
                load: lang.hitch(this, function (response) {
                    if (response.error) {
                        this.errorHandler(response.error);                        
                        return;
                    }                   
                        var layerName = response.featureCollection.layers[0].layerDefinition.name;
                        console.log("layerName: ", layerName)
                        this.addShapefileToMap(response.featureCollection);
                   
                }),
                error: lang.hitch(this, this.errorHandler)

            });            
        },
        errorHandler: function (error) {
            //dom.byId('upload-status').innerHTML = "<p style='color:red'>" + error.message + "</p>";
            console.log("1 errorHandler: ", error.message)
        },
            
        addShapefileToMap: function (featureCollection) {
            //add the shapefile to the map and zoom to the feature collection extent
            //If you want to persist the feature collection when you reload browser you could store the collection in
            //local storage by serializing the layer using featureLayer.toJson()  see the 'Feature Collection in Local Storage' sample
            //for an example of how to work with local storage.
            var fullExtent;
            var layers = [];

            console.log("addShapefileToMap initiated")
            arrayUtils.forEach(featureCollection.layers, function (layer) {
                var infoTemplate = new InfoTemplate("Details", "${*}");
                var featureLayer = new FeatureLayer(layer, {
                    infoTemplate: infoTemplate
                });
                //associate the feature with the popup on click to enable highlight and zoom to
                featureLayer.on('click', function (event) {
                    map.infoWindow.setFeatures([event.graphic]);
                });
                //change default symbol if desired. Comment this out and the layer will draw with the default symbology
                changeRenderer(featureLayer);
                fullExtent = fullExtent ?
                  fullExtent.union(featureLayer.fullExtent) : featureLayer.fullExtent;
                layers.push(featureLayer);
            });
            map.addLayers(layers);
            map.setExtent(fullExtent.expand(1.25), true);

            dom.byId('upload-status').innerHTML = "";
        },

I've added a few console.log prints to try and track down what's going wrong.  No errors, but request doesn't seem to do anything (it's supposed to call "addShapefileToMap" function but seems to just go right to errorHandler: function. 

Line #37 above console.log("setting up request") is the last thing in the console before errorHandler is then reached.  Hopefully just something silly I'm doing.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

OK,

   The the issue is likely the POST vs Get. So in your change to the esri request you added usePost: ture but you put it in the wrong location.

            request({
                url: this.portalUrl + '/sharing/rest/content/features/generate',
                content: myContent,
                form: this.uploadForm,
                handleAs: 'json',
                load: lang.hitch(this, function (response) {
                    if (response.error) {
                        this.errorHandler(response.error);
                        return;
                    }
                    var layerName = response.featureCollection.layers[0].layerDefinition.name;
                    this.uploadstatus.innerHTML = '<b>Loaded: </b>' + layerName;
                    this.addShapefileToMap(response.featureCollection);
                }),
                error: lang.hitch(this, this.errorHandler)
            }, {usePost: 'true'});

View solution in original post

16 Replies
RobertScheitlin__GISP
MVP Emeritus

James,

   Long time ago I converted that sample to a widget.

https://community.esri.com/thread/161017?commentID=530113#comment-530113 

JamesCrandall
MVP Frequent Contributor

Hey thanks! 

Updated error debugging:

If I comment out the callback html attribute, I get past previous error,

var myContent = {

'filetype': 'shapefile',

'publishParameters': JSON.stringify(params),

'f': 'json'//,

//'callback.html': 'textarea'

};

However, I'm now getting this response from the generate request:

{"error":{"code":405,"messageCode":"GWM_0005","message":"Method not supported.","details":[]}}

I notice that it's a GET request, but if I execute the esri sample its a POST.

Prior debugging:

I've got it fit in pretty well I think, however I'm tripping the errorHandler function with "errorHandler:  Unexpected token <". 

The full url: parameter prints out as, "http://www.arcgis.com/sharing/rest/content/features/generate"

This is the complete request as seen in dev tools:

https://www.arcgis.com/sharing/rest/content/features/generate?filetype=shapefile&publishParameters=%...

Thanks again!

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   So does you shapefile work when using the sample? You can force the esri request in your code to use post by adding the usePost option in the request.

JamesCrandall
MVP Frequent Contributor

Robert -- no, it doesn't add the shapefile.  I made sure to zip a shapefile with WGS Web Mercator Aux Sphere too.

You see below that I added a console.log() in the errorHandler, which when I run everything it prints "errorHandler:  Method not supported".

Also, I added "usePost" attribute to the request. 

Thanks!

Here's the full function:

        generateFeatureCollection: function(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\\", "");

            //this.uploadstatus.innerHTML = '<b>Loading… </b>' + name;

            //Define the input params for generate see the rest doc for details
            //http://www.arcgis.com/apidocs/rest/index.html?generate.html
            var params = {
                'name': this.name,
                'targetSR': this.map.spatialReference,
                'maxRecordCount': 1000,
                'enforceInputFileSizeLimit': true,
                'enforceOutputJsonSizeLimit': true
            };

            //generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
            //This should work well when using web mercator.
            var extent = scaleUtils.getExtentForScale(this.map, 40000);
            var resolution = extent.getWidth() / this.map.width;
            params.generalize = true;
            //params.maxAllowableOffset = resolution;
            //params.reducePrecision = true;
            //params.numberOfDigitsAfterDecimal = 0;

            var myContent = {
                'filetype': 'shapefile',
                'publishParameters': JSON.stringify(params),
                'f': 'json'//,
                //'callback.html': 'textarea'
            };

            //use the rest generate operation to generate a feature collection from the zipped shapefile.
            console.log("portalUrl: ", this.portalUrl)
            request({
                url: this.portalUrl + '/sharing/rest/content/features/generate',
                usePost: 'true',
                content: myContent,
                form: this.uploadForm,
                handleAs: 'json',
                load: lang.hitch(this, function (response) {
                    if (response.error) {
                        this.errorHandler(response.error);
                        return;
                    }
                    var layerName = response.featureCollection.layers[0].layerDefinition.name;
                    this.uploadstatus.innerHTML = '<b>Loaded: </b>' + layerName;
                    this.addShapefileToMap(response.featureCollection);
                }),
                error: lang.hitch(this, this.errorHandler)
            });
        },

        errorHandler: function (error) {
            //this.uploadstatus.innerHTML = "<p style='color:red'>" + error.message + "</p>";
            console.log("req: ", request)
            console.log("errorHandler: ", error.message)
        },
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   The use Post part is not important if the shapefile you are using does not work using the esri sample page then there is a bigger issue. Does your shapefile have Z and/or M values?

JamesCrandall
MVP Frequent Contributor

No z or m values.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Have you tried other shapefiles?

JamesCrandall
MVP Frequent Contributor

Yes, and I've used them in the ESRI sandbox example https://developers.arcgis.com/javascript/3/samples/portal_addshapefile/

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  Just to clarify then. You CAN get your shapefiles to work in the above referenced sample but it DOES NOT work in your implementation of the above sample in your widget?