62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
|
|
package app
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"net/http"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
func (s *Server) saveUpload(r *http.Request, field string) (string, bool, error) {
|
||
|
|
if !strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
|
||
|
|
return "", false, nil
|
||
|
|
}
|
||
|
|
file, header, err := r.FormFile(field)
|
||
|
|
if errors.Is(err, http.ErrMissingFile) {
|
||
|
|
return "", false, nil
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
return "", false, err
|
||
|
|
}
|
||
|
|
defer file.Close()
|
||
|
|
|
||
|
|
ext := strings.ToLower(filepath.Ext(header.Filename))
|
||
|
|
switch ext {
|
||
|
|
case ".jpg", ".jpeg", ".png", ".webp", ".gif":
|
||
|
|
default:
|
||
|
|
return "", false, fmt.Errorf("unsupported image type")
|
||
|
|
}
|
||
|
|
name, err := randomToken()
|
||
|
|
if err != nil {
|
||
|
|
return "", false, err
|
||
|
|
}
|
||
|
|
filename := name + ext
|
||
|
|
target := filepath.Join(s.cfg.UploadDir, filename)
|
||
|
|
out, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o644)
|
||
|
|
if err != nil {
|
||
|
|
return "", false, err
|
||
|
|
}
|
||
|
|
defer out.Close()
|
||
|
|
written, err := io.Copy(out, io.LimitReader(file, maxUploadBytes+1))
|
||
|
|
if err != nil {
|
||
|
|
return "", false, err
|
||
|
|
}
|
||
|
|
if written > maxUploadBytes {
|
||
|
|
_ = out.Close()
|
||
|
|
_ = os.Remove(target)
|
||
|
|
return "", false, fmt.Errorf("is too large")
|
||
|
|
}
|
||
|
|
return "/uploads/" + filename, true, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func parseAdminForm(w http.ResponseWriter, r *http.Request, maxBytes int64) error {
|
||
|
|
r.Body = http.MaxBytesReader(w, r.Body, maxBytes)
|
||
|
|
if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
|
||
|
|
return r.ParseMultipartForm(maxBytes)
|
||
|
|
}
|
||
|
|
return r.ParseForm()
|
||
|
|
}
|