diff pkg/wfs/global.go @ 2711:3956de9b6b32

WFS downloader: Implemented GML download to file, ogr2ogr to GeoJSON.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 18 Mar 2019 17:20:02 +0100
parents d7ef169fd0d3
children 2b6f73c30016
line wrap: on
line diff
--- a/pkg/wfs/global.go	Mon Mar 18 17:01:47 2019 +0100
+++ b/pkg/wfs/global.go	Mon Mar 18 17:20:02 2019 +0100
@@ -14,14 +14,23 @@
 package wfs
 
 import (
+	"bufio"
+	"errors"
+	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
+	"os"
 	"os/exec"
+	"path/filepath"
+
+	"gemma.intevation.de/gemma/pkg/config"
 )
 
 var (
 	FormatGeoJSON = []string{"geojson", "application/json"}
 	FormatGML     = []string{
+		"application/gml+xml; version=3.2",
 		"gml2", "gml3", "gml32",
 		"text/xml; subtype=gml/2.1.2",
 		"text/xml; subtype=gml/3.1.1",
@@ -80,7 +89,66 @@
 	return DownloadURLs([]string(gjd), handler)
 }
 
+func places(n int) int {
+	places := 1
+	if n < 0 {
+		places++
+		n = -n
+	}
+	for value := 10; n >= value; value *= 10 {
+		places++
+	}
+	return places
+}
+
 func (gmd GMLDownloader) Download(handler func(string, io.Reader) error) error {
-	// TODO: Implement, me!
-	return nil
+
+	if len(gmd) == 0 {
+		return errors.New("Nothing to download")
+	}
+
+	tmpDir := config.TmpDir()
+	dlDir, err := ioutil.TempDir(tmpDir, "wfs-downloads")
+	if err != nil {
+		return err
+	}
+	defer os.RemoveAll(dlDir)
+	digits := places(len(gmd))
+
+	var files []string
+
+	for i, url := range gmd {
+		fname := filepath.Join(dlDir, fmt.Sprintf("%0*d.gml", digits, i))
+		if err := downloadURL(url, func(_ string, r io.Reader) error {
+			f, err := os.Create(fname)
+			if err != nil {
+				return err
+			}
+			if _, err = io.Copy(f, r); err != nil {
+				f.Close()
+				return err
+			}
+			return f.Close()
+		}); err != nil {
+			return err
+		}
+		files = append(files, fname)
+	}
+
+	out := filepath.Join(dlDir, "out.geojson")
+
+	cmd := exec.Command("ogr2ogr", append([]string{"-f", "GeoJSON", out}, files...)...)
+
+	msg, err := cmd.CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("ogr2ogr failed: %s", msg)
+	}
+
+	in, err := os.Open(out)
+	if err != nil {
+		return err
+	}
+	defer in.Close()
+
+	return handler(gmd[0], bufio.NewReader(in))
 }