Select to view content in your preferred language

problem with creating a point layer from csv

1145
3
07-17-2023 01:12 PM
SvivaManager
Frequent Contributor

I'm trying to create an add data widget with csv input.

using the shapefile to feature Layer sample as a base.

https://developers.arcgis.com/javascript/latest/sample-code/layers-featurelayer-shapefile/

the sample uses generate, and for the publishing parameters Analyze.

 

"Callers can use the Analyze operation to generate the default publishing parameters for the source input."

https://developers.arcgis.com/rest/users-groups-and-items/generate.htm

 

I have a 1 point csv for testing. - attached

the analyze works, but i think I'm not using the generate properly because I'm getting "414 Request-URI Too Large error" on such a small table.

I believe the generate should return an object to automatically work with the addShapefileToMap.

 

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>CodePen - Create a FeatureLayer from a shapefile almost there</title>
  

</head>
<body>
<!-- partial:index.partial.html -->
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="initial-scale=1,maximum-scale=1,user-scalable=no"
    />
    <title>
      Create a FeatureLayer from a shapefile | Sample | ArcGIS Maps SDK for
      JavaScript 4.27
    </title>
    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
      #mainWindow {
        padding: .5em;
        background-color: #fff;
      }
      #mainWindow p, #uploadForm {
          display: block;
          padding: .1em;
        }
    </style>

    <link
      rel="stylesheet"
      href="https://js.arcgis.com/4.27/esri/themes/light/main.css"
    />
    <script src="https://js.arcgis.com/4.27/"></script>

    <script>
      require([
        "esri/config",
        "esri/Map",
        "esri/views/MapView",
        "esri/widgets/Expand",
        "esri/request",
        "esri/layers/FeatureLayer",
        "esri/layers/support/Field",
        "esri/Graphic"
      ], (
        esriConfig,
        Map,
        MapView,
        Expand,
        request,
        FeatureLayer,
        Field,
        Graphic
      ) => {
        const portalUrl = "https://www.arcgis.com";

        document
          .getElementById("uploadForm")
          .addEventListener("change", (event) => {
            const fileName = event.target.value.toLowerCase();

              generateFeatureCollection(fileName);

          });

        const map = new Map({
          basemap: "dark-gray-vector"
        });

        const view = new MapView({
          center: [-41.647, 36.41],
          zoom: 2,
          map: map,
          container: "viewDiv",
          popup: {
            defaultPopupTemplateEnabled: true
          }
        });

        const fileForm = document.getElementById("mainWindow");

        const expand = new Expand({
          expandIcon: "upload",
          view: view,
          content: fileForm
        });

        view.ui.add(expand, "top-right");

        function generateFeatureCollection(fileName) {
          let name = fileName.split(".");
          // Chrome adds c:\fakepath to the value - we need to remove it
          name = name[0].replace("c:\\fakepath\\", "");

          document.getElementById("upload-status").innerHTML =
            "<b>Loading </b>" + name;

          // define the input params for generate see the rest doc for details
          // https://developers.arcgis.com/rest/users-groups-and-items/generate.htm
          const params = {
            name: name,
            targetSR: view.spatialReference,
            maxRecordCount: 1000,
            enforceInputFileSizeLimit: true,
            enforceOutputJsonSizeLimit: true
          };

          // generalize features to 10 meters for better performance
          params.generalize = true;
          params.maxAllowableOffset = 10;
          params.reducePrecision = true;
          params.numberOfDigitsAfterDecimal = 0;

          let myContent = {
            filetype: "csv",
            publishParameters: JSON.stringify(params),
            f: "json"
          };

          ////////////////////////////// analyze csv
          request(portalUrl + "/sharing/rest/content/features/analyze", {
            query: myContent,
            body: document.getElementById("uploadForm"),
            responseType: "json"
          })
            .then((response) => { 
			
            console.log("analyze")            
            console.log(response);
			////////create new query for generate with response from analyze
			let myContent = {
            filetype: "csv",
            publishParameters: JSON.stringify(response.data.publishParameters),
            f: "json"
          };
		  
            /////////////////////////////////////generate 
            request(portalUrl + "/sharing/rest/content/features/generate", {
			//method:"post",
            query: myContent,
            body: response.data.records,
            responseType: "json"
          })
            .then((response) => {
             console.log("generate")
             console.log(response);
              const layerName = response.data.publishParameters.name;
                //response.data.featureCollection.layers[0].layerDefinition.name;
                

              document.getElementById("upload-status").innerHTML =
                "<b>Loaded: </b>" + layerName;
              addShapefileToMap(response.data);
            })
            .catch(errorHandler);
        })
            .catch(errorHandler);
        }
            
            
/////////////////////////////////////////////  all this inside then          


        function errorHandler(error) {
		console.log(error.message)
          document.getElementById("upload-status").innerHTML =
            "<p style='color:red;max-width: 500px;'>" + error.message + "</p>";
        }

        function addShapefileToMap(featureCollection) {
          
          console.log("adding layer")
          // 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
          let sourceGraphics = [];

          const layers = featureCollection.layers.map((layer) => {
            const graphics = layer.featureSet.features.map((feature) => {
              return Graphic.fromJSON(feature);
            });
            sourceGraphics = sourceGraphics.concat(graphics);
            const featureLayer = new FeatureLayer({
              objectIdField: "FID",
              source: graphics,
              fields: layer.layerDefinition.fields.map((field) => {
                return Field.fromJSON(field);
              })
            });
            return featureLayer;
            // associate the feature with the popup on click to enable highlight and zoom to
          });
          map.addMany(layers);
          view.goTo(sourceGraphics).catch((error) => {
            if (error.name != "AbortError") {
              console.error(error);
            }
          });

          document.getElementById("upload-status").innerHTML = "";
        }
      });
    </script>
  </head>

  <body>
    <div id="mainWindow">
      <div>
        <div style="padding-left:4px;">
          <p>
            Download shapefile from
            <a
              href="https://bsvensson.github.io/various-tests/shp/drp_county_boundary.zip"
              >here.</a
            >
          </p>
          <p>Add a zipped shapefile to the map.</p>
          <p>
            Visit the
            <a
              target="_blank"
              href="https://doc.arcgis.com/en/arcgis-online/reference/shapefiles.htm"
              >Shapefiles</a
            >
            help topic for information and limitations.
          </p>
          <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>
          <span
            class="file-upload-status"
            style="opacity:1;"
            id="upload-status"
          ></span>
          <div id="fileInfo"></div>
        </div>
      </div>
    </div>
    <div id="viewDiv"></div>
  </body>
</html>
<!-- partial -->
  
</body>
</html>

 

 

3 Replies
David_McRitchie
Esri Contributor

From looking at this you will need to use a shapefile rather than a csv. From running the application code we get an invalid file format error.

Hope that helps,

David

Esri UK -Technical Support Analyst
0 Kudos
SvivaManager
Frequent Contributor

this is a dist file code , copy it as html file or paste the code on codepen - like the original sample its taken from.

I'm using shapefile sample for a quick start so the function name and title are from the source. the code itself is edited.

shapefile no longer matters when you run this sample, its csv ->analyze response >generate - breaks > add to map.

use the csv I've attached or create one, did it work? did you try something else?

did the analyze return a response - it should ? did the generate? - it didn't for me, i think the paraments i used are wrongly implemented .


 

0 Kudos
JoelBennett
MVP Regular Contributor

If your goal is simply to display a CSV file specified from a file input, a much simpler process is possible that never even has to leave the client. You can see this in the sandbox for the sample by replacing the contents of the script tag on line 37 with the following:

      require([
        "esri/Map",
        "esri/views/MapView",
        "esri/widgets/Expand",
        "esri/layers/CSVLayer"
      ], (Map, MapView, Expand, CSVLayer) => {
        document
          .getElementById("uploadForm")
          .addEventListener("change", (event) => {
            var reader = new FileReader();

            reader.addEventListener("load", function (evt) {
              var blob = new Blob([evt.target.result], {type:"text/plain"});
              var layer = new CSVLayer({url:URL.createObjectURL(blob)});

              map.add(layer);
              expand.collapse();
            });

            reader.readAsText(event.target.files[0]);
          });

        const map = new Map({
          basemap: "dark-gray-vector"
        });

        const view = new MapView({
          center: [-41.647, 36.41],
          zoom: 2,
          map: map,
          container: "viewDiv",
          popup: {
            defaultPopupTemplateEnabled: true
          }
        });

        const fileForm = document.getElementById("mainWindow");

        const expand = new Expand({
          expandIcon: "upload",
          view: view,
          content: fileForm
        });

        view.ui.add(expand, "top-right");
      });

 

It loads the sample CSV you provided just fine:

csv.png