Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'd like to upload shape files using GeoServer REST API and C#. So far, I can create workspaces using the REST API and C#. From GeoServer documentation (specific to cURL), the difference between creating a workspace and uploading a shape file is in the HTTP Method (workspace creation uses POST, shape file uploading uses PUT), ContentType (workspace creation uses application/xml, shape file uploading uses application/zip), and finally there is the --data-binary parameter in shape file uploading.

The code I use for creating workspace is shown below. Can anyone kindly help me refactor this code so that I can use it to upload a shape file. Thanks in advance.

        String gUrl = "http://localhost:8081/geoserver/rest/workspaces";
        WebRequest request = WebRequest.Create(gUrl);

        request.ContentType = "text/xml";
        request.Method = "POST";
        request.Credentials = new NetworkCredential("geoServer-username", "password");

        byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes("<workspace><name>new_workspace_csharp_2</name></workspace>");
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(buffer, 0, buffer.Length);
        requestStream.Close();

        WebResponse response = request.GetResponse();
        Console.Write("Response from GeoServer: " + response);

EDITED: I've managed to make some headway, and I can now upload a shape file using C# and the GeoServer REST API. My refactoring effort, which now works, is shown below:

    public bool UploadShapeFile(string workspace, string dsName, Uri zipUri)
    {
        String fileUri = zipUri.AbsolutePath;
        Console.Write(fileUri);

        byte[] localShapeFile = readLocalShapeFile(fileUri);

        String sUrl = "http://localhost:8081/geoserver/rest/workspaces/cs_ws1/datastores/cs_ds1/file.shp";
        WebRequest request = WebRequest.Create(sUrl);

        request.ContentType = "application/zip";
        request.Method = "PUT";
        request.Credentials = new NetworkCredential("gs-username", "password");

        // byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes(@fileUri);
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(localShapeFile, 0, localShapeFile.Length);
        requestStream.Close();

        WebResponse response = request.GetResponse();
        Console.Write("Response from GeoServer: " + response);


        return false;
    }

    private byte[] readLocalShapeFile(string filePath)
    {
        byte[] buffer;
        FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        try {
            int length = (int)fStream.Length;
            buffer = new byte[length]; 
            int count; 
            int sum = 0; 

            // Read until Read method returns 0 - End of stream reached
            while ((count = fStream.Read(buffer, sum, length - sum)) > 0)
                sum += count;
        }
        finally {
            fStream.Close();
        }

        return buffer;
    }

However, I still believe there can be a more elegant way of doing this. Any suggestions will be highly appreciated.

share|improve this question

1 Answer 1

up vote 3 down vote accepted

I've been able to achieve this using the code segments below. But it'll be great if someone can come up with a better solution.

Part I: Uploading a shape file to GeoServer without PostGIS

    public bool UploadShapeFile(string workspace, string dsName, Uri zipUri)
    {
        String fileUri = zipUri.AbsolutePath;
        Console.Write(fileUri);

        byte[] localShapeFile = readLocalShapeFile(fileUri);

        String sUrl = "http://localhost:8081/geoserver/rest/workspaces/" + 
                        workspace + "/datastores/" + 
                        dsName + "/file.shp";

        WebRequest request = WebRequest.Create(sUrl);

        request.ContentType = "application/zip";
        request.Method = "PUT";
        request.Credentials = new NetworkCredential("geoserver-username", "passwd");

        Stream requestStream = request.GetRequestStream();
        requestStream.Write(localShapeFile, 0, localShapeFile.Length);
        requestStream.Close();

        WebResponse response = request.GetResponse();
        Console.Write("Response from GeoServer: " + response);


        return false;
    }

    private byte[] readLocalShapeFile(string filePath)
    {
        byte[] buffer;
        FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        try {
            int length = (int)fStream.Length; 
            buffer = new byte[length]; 
            int count;
            int sum = 0;

            while ((count = fStream.Read(buffer, sum, length - sum)) > 0)
                sum += count;
        }
        finally {
            fStream.Close();
        }

        return buffer;
    }

Part II: Upload Shape File to GeoServer's PostGIS store First, create a DB Data Store as shown:

    public string CreateDbDataStore(string ws, string dsName)
    {
        String gUrl = "http://localhost:8081/geoserver/rest/workspaces/" + ws + "/datastores.xml";
        WebRequest request = WebRequest.Create(gUrl);

        request.ContentType = "application/xml";
        request.Method = "POST";
        request.Credentials = new NetworkCredential("geoserver-username", "passwd");
        string dbXml = getDbXml(dsName);

        byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes(dbXml);
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(buffer, 0, buffer.Length);
        requestStream.Close();

        WebResponse response = request.GetResponse();
        Console.Write("Response from GeoServer: " + response);

        return dsName;
    }

Then, create a DB Table and FeatureType as shown:

    public bool CreatePostGISTableAndFeatureType(string ws, string ds, string title, string projection)
    {
        string featXml = GetFeatureXml(ds, title, projection);
        string fUrl = "http://localhost:8081/geoserver/rest/workspaces/" + ws +
                        "/datastores/" + ds + "/featuretypes";

        WebRequest request = WebRequest.Create(fUrl);
        request.ContentType = "application/xml";
        request.Method = "POST";
        request.Credentials = new NetworkCredential("geoserver-username", "passwd");

        byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes(featXml);

        Stream requestStream = request.GetRequestStream();
        requestStream.Write(buffer, 0, buffer.Length);
        requestStream.Close();

        WebResponse response = request.GetResponse();

        return false;
    }

    private string GetFeatureXml(string dsName, string title, string projection)
    {
        string fXml = "<featureType>" +
                            "<name>" + dsName + "</name>" +
                            "<nativeName>" + dsName + "</nativeName>" +
                            "<title>" + title + "</title>" +
                            "<srs>" + projection + "</srs>" +
                            "<attributes>" +
                                "<attribute>" +
                                    "<name>the_geom</name>" +
                                    "<binding>com.vividsolutions.jts.geom.Point</binding>" +
                                "</attribute>" +
                                "<attribute>" +
                                    "<name>description</name>" +
                                    "<binding>java.lang.String</binding>" +
                                "</attribute>" +
                                "<attribute>" +
                                    "<name>timestamp</name>" +
                                    "<binding>java.util.Date</binding>" +
                                "</attribute>" +
                            "</attributes>" +
                        "</featureType>";
        return fXml;
    }

Finally, upload the shape file using the UploadShapeFile(..) method above, specifying the previously created (postgis) data store as the dsName.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.