Select to view content in your preferred language

Geoprocessing Service Returns Empty GeoJSON via ArcGIS JavaScript SDK but Works in ArcGIS Map Viewer

243
0
08-22-2024 11:12 AM
SafaHamed
New Contributor

Hello everyone,

I’m working on a project where I need to convert CAD files (DWG) to GeoJSON format using a geoprocessing service. The service works as expected when I test it in the ArcGIS Map Viewer—it returns the correct GeoJSON output. However, when I try to run the same service using the ArcGIS Maps SDK for JavaScript, the output is an empty GeoJSON.

Here’s a brief overview of my setup:

Front-End Code (HTML + JavaScript):

 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>CAD to JSON Geoprocessing | ArcGIS Maps SDK for JavaScript</title>
    <style>
        html, body, #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
        #sidebar {
            position: absolute;
            top: 0;
            right: 0;
            height: 85%;
            width: 320px;
            background-color: rgba(0, 0, 0, 0.7);
            overflow-y: auto;
            padding: 10px;
        }
        .label {
            color: white;
        }
        #processButton {
            border: none;
            background-color: rgba(229, 89, 52, 0.75);
            color: #fff;
            margin: 10px 0;
            width: 100%;
            padding: 10px;
            text-align: center;
            cursor: pointer;
            font-size: 1em;
        }
    </style>
    <link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/dark/main.css" />
    <script src="https://js.arcgis.com/4.30/"></script>
    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "esri/rest/geoprocessor",
            "esri/layers/GraphicsLayer",
            "esri/Graphic",
            "esri/widgets/Legend"
        ], (Map, MapView, geoprocessor, GraphicsLayer, Graphic, Legend) => {
            const processButton = document.getElementById("processButton");
            processButton.addEventListener("click", processCADFile);

            const message = document.getElementById("message");
            const fileInput = document.getElementById("fileInput");

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

            const view = new MapView({
                container: "viewDiv",
                map: map,
                center: [55.3833, 25.3575],
                zoom: 12
            });

            const graphicsLayer = new GraphicsLayer();
            map.add(graphicsLayer);

            const gpUrl = "https://<my-server>/server/rest/services/FromDWG_1/GPServer/FromDWG";

            function processCADFile() {
                const file = fileInput.files[0];
                if (!file) {
                    message.innerText = "Please select a CAD file.";
                    return;
                }

                const formData = new FormData();
                formData.append("file", file);

                message.innerText = "Uploading file...";

                fetch("https://<my-server>/server/rest/services/FromDWG_1/GPServer/uploads/upload", {
                    method: "POST",
                    body: formData
                })
                .then(response => response.text())
                .then(html => {
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(html, "text/html");
                    const itemIDElement = doc.querySelector('a[href^="/server/rest/services/FromDWG_1/GPServer/uploads/i"]');
                    if (itemIDElement) {
                        const itemID = itemIDElement.textContent.trim();
                        submitGeoprocessingJob(itemID);
                    } else {
                        throw new Error("Could not find item ID in the response");
                    }
                })
                .catch(error => {
                    message.innerText = `Error uploading file: ${error.message}`;
                });
            }

            function submitGeoprocessingJob(itemID) {
                message.innerText = "Submitting geoprocessing job...";

                const params = {
                    input_dwg: {
                        "url": `https://<my-server>/server/rest/services/FromDWG_1/GPServer/uploads/${itemID}`
                    }
                };

                geoprocessor.submitJob(gpUrl, params)
                    .then(jobInfo => {
                        const options = {
                            statusCallback: jobInfo => {
                                message.innerText = `Job status: ${jobInfo.jobStatus}`;
                            }
                        };
                        return jobInfo.waitForJobCompletion(options);
                    })
                    .then(jobInfo => {
                        return jobInfo.fetchResultData("output_json");
                    })
                    .then(result => {
                        displayResults(result.value);
                    })
                    .catch(error => {
                        message.innerText = `Error processing CAD file: ${error.message}`;
                    });
            }

            function displayResults(geoJSON) {
                graphicsLayer.removeAll();

                const features = geoJSON.features;
                features.forEach(feature => {
                    let geometry, symbol;

                    switch (feature.geometry.type) {
                        case "Point":
                            geometry = {
                                type: "point",
                                longitude: feature.geometry.coordinates[0],
                                latitude: feature.geometry.coordinates[1]
                            };
                            symbol = {
                                type: "simple-marker",
                                color: [226, 119, 40],
                                outline: { color: [255, 255, 255], width: 1 }
                            };
                            break;
                        case "LineString":
                            geometry = {
                                type: "polyline",
                                paths: [feature.geometry.coordinates]
                            };
                            symbol = {
                                type: "simple-line",
                                color: [226, 119, 40],
                                width: 2
                            };
                            break;
                        case "Polygon":
                            geometry = {
                                type: "polygon",
                                rings: feature.geometry.coordinates
                            };
                            symbol = {
                                type: "simple-fill",
                                color: [226, 119, 40, 0.5],
                                outline: { color: [255, 255, 255], width: 1 }
                            };
                            break;
                    }

                    const graphic = new Graphic({
                        geometry: geometry,
                        symbol: symbol,
                        attributes: feature.properties
                    });

                    graphicsLayer.add(graphic);
                });

                view.goTo(graphicsLayer.graphics);
                message.innerText = `Displayed ${features.length} features on the map.`;
            }
        });
    </script>
</head>
<body>
    <div id="viewDiv">
        <div id="sidebar" class="esri-widget">
            <h3 class="label">CAD to JSON Converter</h3>
            <input type="file" id="fileInput" accept=".dwg,.dxf" class="label">
            <button id="processButton">Process CAD File</button>
            <div id="message" class="label"></div>
            <div id="legendDiv" class="esri-widget"></div>
        </div>
    </div>
</body>
</html>

 

 

 

Geoprocessing Service Code (Python/ArcPy):

 

 

 

import arcpy
import os
import json
from datetime import datetime
import uuid

# Constants for server and Pro environments
SERVER_PROD_NAME = 'Server'
PRO_PROD_NAME = 'ArcGISPro'

def convert_to_geojson(feature):
"""Converts a single Esri JSON feature to GeoJSON format."""
geojson_feature = {
"type": "Feature",
"geometry": feature["geometry"],
"properties": {}
}
for key, value in feature["attributes"].items():
if isinstance(value, datetime):
# Convert datetime objects to string
geojson_feature["properties"][key] = value.isoformat()
else:
geojson_feature["properties"][key] = value
return geojson_feature

def generate_unique_file_name(extension):
"""Generate a unique filename using UUID."""
guid = str(uuid.uuid1())
filename = f"{guid}.{extension}"
return filename

def get_output_paths():
"""Return the list of output paths and the corresponding URL."""
download_paths = [
r"<server-path-1>",
r"<server-path-2>"
]
download_url = "https://<my-server>/Output/"
return download_paths, download_url

def process_dwg_to_geojson(dwgFilePath, outJsonFile):
try:
arcpy.AddMessage(f"Processing DWG file: {dwgFilePath}")
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(4326)

# Check if running on a server or in ArcGIS Pro
product_name = arcpy.GetInstallInfo()['ProductName']
if (product_name == SERVER_PROD_NAME):
# Get the output paths and URL
output_paths, output_url = get_output_paths()
else:
output_paths = [arcpy.env.scratchFolder]
output_url = None

# Handle file renaming and unique file generation
unique_filename = generate_unique_file_name("geojson")
geoJsonFilePaths = [os.path.join(path, unique_filename) for path in output_paths]

# List all geometry types in the DWG file
arcpy.env.workspace = dwgFilePath
feature_classes = arcpy.ListFeatureClasses()

geojson_features = []

for fc in feature_classes:
geometryType = arcpy.Describe(fc).shapeType
arcpy.AddMessage(f"Processing geometry type: {geometryType}")

with arcpy.da.SearchCursor(fc, ["SHAPE@", "*"]) as cursor:
for row in cursor:
geometry = row[0].__geo_interface__
attributes = {field: row[idx] for idx, field in enumerate(cursor.fields) if field != "SHAPE@"}
esri_feature = {"geometry": geometry, "attributes": attributes}
geojson_features.append(convert_to_geojson(esri_feature))

geojson = {
"type": "FeatureCollection",
"features": geojson_features
}

# Write the GeoJSON output to file on both servers
for geoJsonFilePath in geoJsonFilePaths:
with open(geoJsonFilePath, 'w') as geoJsonFile:
json.dump(geojson, geoJsonFile)
arcpy.AddMessage(f"GeoJSON created at: {geoJsonFilePath}")

if output_url:
# Generate the web-accessible URL
webUrl = os.path.join(output_url, unique_filename).replace("\\", "/")
arcpy.AddMessage(f"GeoJSON available at: {webUrl}")
arcpy.SetParameterAsText(1, webUrl)
else:
arcpy.SetParameterAsText(1, geoJsonFilePaths[0])

except Exception as e:
arcpy.AddError(f"An error occurred: {str(e)}")
raise

if __name__ == "__main__":
dwgFilePath = arcpy.GetParameterAsText(0)
outJsonFile = arcpy.GetParameterAsText(1)

if not os.path.isfile(dwgFilePath):
arcpy.AddError("The specified DWG file does not exist.")
raise FileNotFoundError("The specified DWG file does not exist.")

process_dwg_to_geojson(dwgFilePath, outJsonFile)

 

I would greatly appreciate any help in identifying why the service returns an empty GeoJSON when run through the JavaScript SDK but works fine in the ArcGIS Map Viewer.

Thanks in advance for your support!

 

Tags (2)
0 Kudos
0 Replies