Mercurial > gemma
changeset 4305:0f467a839fe2
Moved stretches as shape file download to separate file.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 02 Sep 2019 18:01:45 +0200 |
parents | fee5794f3b7a |
children | 2336f75637d1 |
files | pkg/controllers/shapestretches.go pkg/controllers/stretches.go |
diffstat | 2 files changed, 225 insertions(+), 199 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/controllers/shapestretches.go Mon Sep 02 18:01:45 2019 +0200 @@ -0,0 +1,224 @@ +// This is Free Software under GNU Affero General Public License v >= 3.0 +// without warranty, see README.md and license for details. +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// License-Filename: LICENSES/AGPL-3.0.txt +// +// Copyright (C) 2019 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Sascha L. Teichmann <sascha.teichmann@intevation.de> + +package controllers + +import ( + "archive/zip" + "database/sql" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gorilla/mux" + "github.com/jonas-p/go-shp" + + "gemma.intevation.de/gemma/pkg/config" + "gemma.intevation.de/gemma/pkg/middleware" + "gemma.intevation.de/gemma/pkg/wkb" +) + +const ( + selectStretchSQL = ` +SELECT + id, + isrs_asText(lower(stretch)), + isrs_asText(upper(stretch)), + ST_AsBinary(area::geometry), + objnam, + nobjnam, + date_info, + source_organization +FROM waterway.stretches WHERE + staging_done AND + name = $1` + + selectStretchCountriesSQL = ` +SELECT country_code FROM waterway.stretch_countries +WHERE stretches_id = $1 +ORDER BY country_code` +) + +func stretchShapeDownload(rw http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + name := vars["name"] + + conn := middleware.GetDBConn(req) + ctx := req.Context() + + tx, err := conn.BeginTx(ctx, &sql.TxOptions{ReadOnly: true}) + if err != nil { + http.Error( + rw, fmt.Sprintf("DB error: %v.", err), + http.StatusInternalServerError) + return + } + defer tx.Rollback() + + var ( + id int64 + lower, upper string + data []byte + objnam string + nobjnam sql.NullString + dateInfo time.Time + source string + ) + + switch err := tx.QueryRowContext(ctx, selectStretchSQL, name).Scan( + &id, + &lower, &upper, + &data, + &objnam, &nobjnam, + &dateInfo, + &source, + ); { + case err == sql.ErrNoRows: + http.NotFound(rw, req) + return + case err != nil: + http.Error( + rw, fmt.Sprintf("DB error: %v.", err), + http.StatusInternalServerError) + return + } + + var countries []string + + if err := func() error { + rows, err := tx.Query(selectStretchCountriesSQL, id) + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + var country string + if err := rows.Scan(&country); err != nil { + return err + } + countries = append(countries, country) + } + + return rows.Err() + }(); err != nil { + http.Error( + rw, fmt.Sprintf("DB error: %v.", err), + http.StatusInternalServerError) + return + } + + var geom wkb.MultiPolygonGeom + + if err := geom.FromWKB(data); err != nil { + http.Error( + rw, fmt.Sprintf("Decoding WKB error: %v.", err), + http.StatusInternalServerError) + return + } + + tmp := config.TmpDir() + + dir, err := ioutil.TempDir(tmp, "stretch-download") + if err != nil { + http.Error( + rw, fmt.Sprintf("Cannot create temp dir: %v.", err), + http.StatusInternalServerError) + return + } + defer os.RemoveAll(dir) + + shpDir := filepath.Join(dir, "stretch") + + if err := os.Mkdir(shpDir, os.ModePerm); err != nil { + http.Error( + rw, fmt.Sprintf("Cannot create temp dir: %v.", err), + http.StatusInternalServerError) + return + } + + filename := filepath.Join(shpDir, "stretch") + + if err := func() error { + writer, err := shp.Create(filename, shp.POLYGON) + if err != nil { + return err + } + defer writer.Close() + + // TODO: Write geometry + + return nil + }(); err != nil { + http.Error( + rw, fmt.Sprintf("creating shapefile failed: %v.", err), + http.StatusInternalServerError) + return + } + + entries, err := func() ([]os.FileInfo, error) { + f, err := os.Open(shpDir) + if err != nil { + return nil, err + } + defer f.Close() + return f.Readdir(-1) + }() + if err != nil { + http.Error( + rw, fmt.Sprintf("cannot read directory: %v.", err), + http.StatusInternalServerError) + return + } + + rw.Header().Set("Content-Type", "application/zip") + rw.Header().Set("Content-Disposition", `attachment; filename="stretch.zip"`) + + zipfile := zip.NewWriter(rw) + defer zipfile.Close() + + now := time.Now() + + base := filepath.Base(shpDir) + for _, info := range entries { + if !info.Mode().IsRegular() { + continue + } + if err := func() error { + srcFile, err := os.Open(filepath.Join(shpDir, info.Name())) + if err != nil { + return err + } + defer srcFile.Close() + header := &zip.FileHeader{ + Name: base + "/" + info.Name(), + Method: zip.Deflate, + Modified: now, + } + out, err := zipfile.CreateHeader(header) + if err != nil { + return err + } + _, err = io.Copy(out, srcFile) + return err + }(); err != nil { + log.Printf("error: cannot write file: %v\n", err) + return + } + } +}
--- a/pkg/controllers/stretches.go Mon Sep 02 17:57:44 2019 +0200 +++ b/pkg/controllers/stretches.go Mon Sep 02 18:01:45 2019 +0200 @@ -4,7 +4,7 @@ // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // -// Copyright (C) 2099 by via donau +// Copyright (C) 2019 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // @@ -14,28 +14,20 @@ package controllers import ( - "archive/zip" "context" "database/sql" "encoding/csv" "fmt" - "io" - "io/ioutil" "log" "net/http" - "os" - "path/filepath" "runtime" "strings" "sync" "time" "github.com/gorilla/mux" - "github.com/jonas-p/go-shp" - "gemma.intevation.de/gemma/pkg/config" "gemma.intevation.de/gemma/pkg/middleware" - "gemma.intevation.de/gemma/pkg/wkb" ) const ( @@ -665,193 +657,3 @@ log.Printf("error: %v\n", err) } } - -const ( - selectStretchSQL = ` -SELECT - id, - isrs_asText(lower(stretch)), - isrs_asText(upper(stretch)), - ST_AsBinary(area::geometry), - objnam, - nobjnam, - date_info, - source_organization -FROM waterway.stretches WHERE - staging_done AND - name = $1` - - selectStretchCountriesSQL = ` -SELECT country_code FROM waterway.stretch_countries -WHERE stretches_id = $1 -ORDER BY country_code` -) - -func stretchShapeDownload(rw http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - name := vars["name"] - - conn := middleware.GetDBConn(req) - ctx := req.Context() - - tx, err := conn.BeginTx(ctx, &sql.TxOptions{ReadOnly: true}) - if err != nil { - http.Error( - rw, fmt.Sprintf("DB error: %v.", err), - http.StatusInternalServerError) - return - } - defer tx.Rollback() - - var ( - id int64 - lower, upper string - data []byte - objnam string - nobjnam sql.NullString - dateInfo time.Time - source string - ) - - switch err := tx.QueryRowContext(ctx, selectStretchSQL, name).Scan( - &id, - &lower, &upper, - &data, - &objnam, &nobjnam, - &dateInfo, - &source, - ); { - case err == sql.ErrNoRows: - http.NotFound(rw, req) - return - case err != nil: - http.Error( - rw, fmt.Sprintf("DB error: %v.", err), - http.StatusInternalServerError) - return - } - - var countries []string - - if err := func() error { - rows, err := tx.Query(selectStretchCountriesSQL, id) - if err != nil { - return err - } - defer rows.Close() - - for rows.Next() { - var country string - if err := rows.Scan(&country); err != nil { - return err - } - countries = append(countries, country) - } - - return rows.Err() - }(); err != nil { - http.Error( - rw, fmt.Sprintf("DB error: %v.", err), - http.StatusInternalServerError) - return - } - - var geom wkb.MultiPolygonGeom - - if err := geom.FromWKB(data); err != nil { - http.Error( - rw, fmt.Sprintf("Decoding WKB error: %v.", err), - http.StatusInternalServerError) - return - } - - tmp := config.TmpDir() - - dir, err := ioutil.TempDir(tmp, "stretch-download") - if err != nil { - http.Error( - rw, fmt.Sprintf("Cannot create temp dir: %v.", err), - http.StatusInternalServerError) - return - } - defer os.RemoveAll(dir) - - shpDir := filepath.Join(dir, "stretch") - - if err := os.Mkdir(shpDir, os.ModePerm); err != nil { - http.Error( - rw, fmt.Sprintf("Cannot create temp dir: %v.", err), - http.StatusInternalServerError) - return - } - - filename := filepath.Join(shpDir, "stretch") - - if err := func() error { - writer, err := shp.Create(filename, shp.POLYGON) - if err != nil { - return err - } - defer writer.Close() - - // TODO: Write geometry - - return nil - }(); err != nil { - http.Error( - rw, fmt.Sprintf("creating shapefile failed: %v.", err), - http.StatusInternalServerError) - return - } - - entries, err := func() ([]os.FileInfo, error) { - f, err := os.Open(shpDir) - if err != nil { - return nil, err - } - defer f.Close() - return f.Readdir(-1) - }() - if err != nil { - http.Error( - rw, fmt.Sprintf("cannot read directory: %v.", err), - http.StatusInternalServerError) - return - } - - rw.Header().Set("Content-Type", "application/zip") - rw.Header().Set("Content-Disposition", `attachment; filename="stretch.zip"`) - - zipfile := zip.NewWriter(rw) - defer zipfile.Close() - - now := time.Now() - - base := filepath.Base(shpDir) - for _, info := range entries { - if !info.Mode().IsRegular() { - continue - } - if err := func() error { - srcFile, err := os.Open(filepath.Join(shpDir, info.Name())) - if err != nil { - return err - } - defer srcFile.Close() - header := &zip.FileHeader{ - Name: base + "/" + info.Name(), - Method: zip.Deflate, - Modified: now, - } - out, err := zipfile.CreateHeader(header) - if err != nil { - return err - } - _, err = io.Copy(out, srcFile) - return err - }(); err != nil { - log.Printf("error: cannot write file: %v\n", err) - return - } - } -}