What is this?

This is basically where I write down stuff that I work with at my job as a GIS Technical Analyst (previously system administrator). I do it because it's practical for documentation purposes (although, I remove stuff that might be a security breach) and I hope it can be of use to someone out there. I frequently search the net for help myself, and this is my way of contributing.

Tuesday, December 31, 2013

Uploading a file to FME Server using Dojo and Internet Explorer

Not being the greatest of Javascript programmers I was struggling with some FME/Javascript issues here for a while. I needed to create a small Javascript application that should do the following:
  1. Upload a file (Excel) to a FME Server.
  2. Run a workspace (job) on the FME server using this file as input.
  3. Wait for the job to finish.
  4. Display status, and if successful: provide a link to download the transformed file from the FME server.
Safe software have lots of Javascript examples on their "FME Server Playground" pages. The one called "Full Data Upload Example" was a good start, but it had several issues for a someone who doesn't do programming often:
  1. The script does not work in Internet Explorer
  2. The script needs to reside ON the FME server to avoid CORS (cross origin resource sharing) issues.
Here's what I did to solve the issues:
  1. IE does not handle the JSON response the same way other browsers do. Rather than pick up the JSON response text and continue the script, IE will display a file download prompt. I had some assistance from a helpful guy at Safe support and we sorted that out. The javascript ended up quite messy though, so I decided to go for a better solution. The application is meant to display a map using ESRIs ArcGIS Javascript API. In other words I am already using the Dojo toolkit in the application, so I decided to rewrite the script to use Dojo instead.
  2. Normally I would not mind having the script running on the FME server, but this application/script will be included as part of a .net-based application, and I don't like scattering bits and pieces around - in other words - it must reside a IIS server. Since many of our applications are map-centric we simply use ESRIs proxy.ashx page (https://developers.arcgis.com/en/javascript/jshelp/ags_proxy.html) to deal with CORS issues. It's real simple and does what its supposed to do (plus it can handle tokens/security when you use ArcGIS Server which is initially why we started using it).
So if you are a GIS/Tech person and find yourself in a situation where your .net/ArcGIS Javascript based application need to upload a file to a FME server and grab the transformed file - perhaps you can save some time by looking at this script:



The repository/service referenced in the script is running at our FME server at my job, if for some reason it should be unavailable you can create your own FME workspace that does the same thing. It really is a basic workspace that does the following:
  • Read a excel spreadsheet (using a XLSX_Reader)
  • Write a csv-file using dynamic properties from the excel spreadsheet
When publishing to FME Server it only requires the "Data Download"-service to be registered.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>FME Data upload</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.7/js/esri/css/esri.css">

    <script>dojoConfig = { parseOnLoad: true }</script>
    <script src="//js.arcgis.com/3.7/"></script>

    <script>
        var filePath = "";
        require([
            "dijit/form/Button",
            "dojo/request/xhr",
            "dojo/dom",
            "dojo/json",
            "dojox/form/Uploader",
            "dojox/form/uploader/plugins/IFrame",
            "dojo/domReady!"
        ], function (
            Button,
            xhr,
            dom,
            JSON,
            uploader) {
            // Generate upload form. Dojo will automatically use iFrame for IE, HTML5 for the rest
            var uploadForm = new dojox.form.Uploader({
                name: "file",
                id: "file",
                label: "Upload File",
                multiple: false,
                uploadOnSelect: true,
                onComplete: uploadCallback,
                url: "proxy.ashx?http://fme.miljodirektoratet.no/fmedataupload/kp_repo/xls_to_csv.fmw?opt_extractarchive=true&opt_pathlevel=3&opt_fullpath=true&opt_responseformat=json"
            });
            dom.byId("uploadDiv").appendChild(uploadForm.domNode);
            uploadForm.startup();

            // Callback: File has been uploaded - check the result
            function uploadCallback(dataUpload, ioargs, widgetRef) {
                try {
                    if (dataUpload.serviceResponse.statusInfo.status == "success") {
                        // go through response for all uploaded files (pointless in this example as we only allow one file - but useful if you must upload multiple files)
                        for (i = 0; i < dataUpload.serviceResponse.files.file.length; ++i) {
                            dom.byId("uploadStatusDiv").innerHTML = "File: " + dataUpload.serviceResponse.files.file[i].name + " was uploaded" + "
";
                            dom.byId("jobResultDiv").innerHTML = ""// clear jobResultDiv in case this is not the first file uploaded in this session
                            filePath = dataUpload.serviceResponse.files.file[i].path;
                            // Check that filename contains .xls or .xlsx
                            try {
                                var extensionCheckResult = dataUpload.serviceResponse.files.file[i].name.match(/\.xlsx|\.xls$/i);
                                if (extensionCheckResult[0].toLowerCase() == ".xls" || extensionCheckResult[0].toLowerCase() == ".xlsx") {
                                    dom.byId("jobResultDiv").innerHTML += ("File type ok (" + extensionCheckResult + ")
"
);
                                    if (/[A-Z]+/.test(extensionCheckResult)) {
                                        dom.byId("jobResultDiv").innerHTML += ("Warning: FME Server does not like upper case letters in file name extensions.
");
                                    }
                                    jobStartButton.setDisabled(false);
                                    uploadForm.setDisabled(true);
                                }
                                else {
                                    dom.byId("jobResultDiv").innerHTML += ("File type wrong (" + extensionCheckResult[0] + ")
");
                                }
                            }
                            catch (error) {
                                dom.byId("jobResultDiv").innerHTML += ("Problem determining file type (" + error + ")
");
                            }
                        }
                    } else {
                        dom.byId("uploadStatusDiv").innerHTML = "Unable uploading file(s)
";
                    }
                }
                catch (err) {
                    console.log(err);
                }
            }

            // Create the button that lets you run the workspace job
            var jobStartButton = new Button({
                label: "Run workspace",
                disabled: true,
                onClick: function () {
                    dom.byId("jobResultDiv").innerHTML += "Workspace is starting, wait...
";
                    xhr("proxy.ashx?http://fme.miljodirektoratet.no/fmedatadownload/kp_repo/xls_to_csv.fmw?SourceDataset_XLSXR=" + filePath + "&opt_responseformat=json", {
                        handleAs: "json",
                        method: "POST"
                    }).then(function (dataRunWS) {
                        dom.byId("jobResultDiv").innerHTML += "Status: " + dataRunWS.serviceResponse.statusInfo.status + "
";
                        dom.byId("jobResultDiv").innerHTML += "Download file at: " + dataRunWS.serviceResponse.url + "
";
                        jobStartButton.setDisabled(true);       // Only allow button workspace to be run once
                        uploadForm.setDisabled(false);          // reactivate uploadForm for another file
                    });
                }
            }, "jobStartButtonDiv");
            jobStartButton.startup();
        });
    </script>
</head>
<body class="claro">
    <h1>FME File Upload</h1>
    <div id="uploadDiv"></div>
    <div id="uploadStatusDiv"> </div>
    <div id="jobStartButtonDiv"></div>
    <div id="jobResultDiv"></div>
</body>

</html>



2 comments:

  1. Mohegan Sun to reopen casino - KTNV
    Mohegan Sun 계룡 출장샵 in 세종특별자치 출장샵 Uncasville, 김천 출장마사지 Conn., will reopen its 동두천 출장샵 casino Thursday, May 29, when its new 경주 출장마사지 $100 million casino will open in the

    ReplyDelete