staging.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package fileupload
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "os"
  8. )
  9. func (r *Registry) copyLimitedToTemp(file io.Reader, maxBytes int64) (string, int64, error) {
  10. tmp, err := os.CreateTemp(r.baseDir, "olu-")
  11. if err != nil {
  12. return "", 0, fmt.Errorf("create temp file: %w", err)
  13. }
  14. path := tmp.Name()
  15. n, err := io.Copy(tmp, io.LimitReader(file, maxBytes+1))
  16. cerr := tmp.Close()
  17. return finalizeLimitedCopy(path, n, err, cerr, maxBytes)
  18. }
  19. func finalizeLimitedCopy(path string, n int64, err, cerr error, maxBytes int64) (string, int64, error) {
  20. if err != nil {
  21. _ = os.Remove(path)
  22. return "", 0, fmt.Errorf("read upload: %w", err)
  23. }
  24. if cerr != nil {
  25. _ = os.Remove(path)
  26. return "", 0, fmt.Errorf("close temp file: %w", cerr)
  27. }
  28. if n > maxBytes {
  29. _ = os.Remove(path)
  30. return "", n, fmt.Errorf("file exceeds maximum size of %d bytes", maxBytes)
  31. }
  32. return path, n, nil
  33. }
  34. func detectMimeFromPath(path string) (string, error) {
  35. header := make([]byte, 512)
  36. f, err := os.Open(path)
  37. if err != nil {
  38. return "", err
  39. }
  40. defer f.Close()
  41. readN, readErr := f.Read(header)
  42. if readErr != nil && !errors.Is(readErr, io.EOF) {
  43. return "", fmt.Errorf("read sniff buffer: %w", readErr)
  44. }
  45. return http.DetectContentType(header[:readN]), nil
  46. }