view pkg/misc/http.go @ 5415:4ad68ab239b7 marking-single-beam

Factored creation of default class breaks in SR import to be reused with markings, too.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 07 Jul 2021 12:01:28 +0200
parents 6237e6165041
children 1222b777f51f
line wrap: on
line source

// 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) 2018 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>

package misc

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"gemma.intevation.de/gemma/pkg/config"
)

// StoreUploadedFile stores a file upload file from
// a given HTTP request identified by a given field name
// in a file with a path build by the config.TmpDir and
// the given file name.
// If the file is long than the given limit maxSize
// this function returns an error.
func StoreUploadedFile(
	req *http.Request,
	field, fname string,
	maxSize int64) (string, error) {
	return StoreUploadedFileCheck(req, field, fname, maxSize, false)
}

func StoreUploadedFileCheck(req *http.Request, field, fname string, maxSize int64, errorOverMax bool) (string, error) {

	// Check for direct upload.
	f, _, err := req.FormFile(field)
	if err != nil {
		return "", err
	}
	defer f.Close()

	dir, err := ioutil.TempDir(config.TmpDir(), field)
	if err != nil {
		return "", err
	}

	o, err := os.Create(filepath.Join(dir, fname))
	if err != nil {
		os.RemoveAll(dir)
		return "", err
	}

	out := bufio.NewWriter(o)

	// Little trick to check if we are over the limit.
	size := maxSize
	if errorOverMax {
		size++
	}

	cleanup := func() {
		o.Close()
		os.RemoveAll(dir)
	}

	r, err := io.Copy(out, io.LimitReader(f, size))
	if err != nil {
		cleanup()
		return "", err
	}

	if errorOverMax && r > maxSize {
		cleanup()
		return "", fmt.Errorf("upload exceeded limit of %d bytes", maxSize)
	}

	if err = out.Flush(); err != nil {
		cleanup()
		return "", err
	}

	if err := o.Close(); err != nil {
		os.RemoveAll(dir)
		return "", err
	}

	return dir, nil
}