files

package
v0.0.0-...-5ef2174 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 12, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package files provides helpers for validating, processing, and storing user-uploaded files (images and PDFs). It is intentionally free of domain knowledge so every application domain can use it generically.

Typical upload flow

  1. Receive multipart file from the HTTP handler (r io.Reader, size int64).
  2. Call ValidateImage / ValidatePDF to check magic bytes and size.
  3. For images: call ProcessImage to decode any supported format, optionally resize, and re-encode as PNG.
  4. Call files.New(cfg).UploadImage / UploadPDF to store in S3 with an integrity-verified checksum and a structured key.
  5. Persist the returned key; use AccessURLForUser to generate time-limited presigned GET links that enforce tenant/user ownership.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrFileTooLarge     = errors.New("file exceeds maximum allowed size")
	ErrInvalidFormat    = errors.New("file format not allowed")
	ErrChecksumMismatch = errors.New("checksum verification failed")
	ErrEmptyFile        = errors.New("file is empty")
	ErrAccessDenied     = errors.New("file access denied")
)

Sentinel errors.

View Source
var DefaultImageConstraints = ImageConstraints{
	MaxBytes:  10 * 1024 * 1024,
	MaxWidth:  4096,
	MaxHeight: 4096,
	MinWidth:  1,
	MinHeight: 1,
}

DefaultImageConstraints is a sensible default: 10 MB, max 4096 × 4096 px.

View Source
var DefaultPDFConstraints = PDFConstraints{
	MaxBytes: 25 * 1024 * 1024,
}

DefaultPDFConstraints is a sensible default: 25 MB.

Functions

func DecodeImage

func DecodeImage(r io.Reader, format ImageFormat) (image.Image, error)

DecodeImage decodes r as the given format and returns the in-memory image. Accepts any ImageFormat constant; returns an error for unknown formats.

func Dimensions

func Dimensions(r io.Reader, format ImageFormat) (width, height int, err error)

Dimensions returns the pixel dimensions of the image in r for the given format without fully decoding the pixel data (header-only read where supported by the codec). r is consumed; buffer externally if re-use is needed.

func KeyBelongsTo

func KeyBelongsTo(key, tenant, userID string) bool

KeyBelongsTo reports whether key was issued for the given tenant and userID. Use this before handing out presigned URLs to enforce ownership at the application layer.

func KeyPrefix

func KeyPrefix(tenant, domain, userID string) string

KeyPrefix returns the S3 prefix that lists all objects for a given tenant → domain → user path. Leave userID or domain empty to get a broader prefix.

KeyPrefix("clinic-uuid", "patients", "user-uuid") → "clinic-uuid/patients/user-uuid/"
KeyPrefix("clinic-uuid", "patients", "")          → "clinic-uuid/patients/"
KeyPrefix("clinic-uuid", "", "")                  → "clinic-uuid/"

func KeySegments

func KeySegments(key string) (tenant, domain, userID, filename string, err error)

KeySegments parses a key produced by NewKey and returns its components. Returns an error if the key does not have the expected 4-segment structure.

func MD5Base64

func MD5Base64(r io.Reader) (string, error)

MD5Base64 reads r to EOF and returns the base64-encoded MD5 digest. This matches the format expected by the S3 Content-MD5 header.

func NewKey

func NewKey(p KeyParams) string

NewKey generates a unique, hierarchical S3 object key from p. A fresh UUID v4 is generated on every call so each upload gets its own key.

func ProcessImage

func ProcessImage(r io.Reader, format ImageFormat, opts *ResizeOpts) ([]byte, error)

ProcessImage decodes r (in the given format), optionally resizes it, and returns the result encoded as PNG. Pass nil opts to skip resizing.

This is the one-call helper for the common upload path:

pngBytes, err := files.ProcessImage(r, format, &files.ResizeOpts{Width: 800, Fit: true})

func Resize

func Resize(src image.Image, opts ResizeOpts) (image.Image, error)

Resize returns a new image scaled to the dimensions described by opts using high-quality Catmull-Rom resampling.

func SHA256Base64

func SHA256Base64(r io.Reader) (string, error)

SHA256Base64 reads r to EOF and returns the standard base64-encoded SHA-256 digest. This is the exact format required by the AWS S3 ChecksumSHA256 field.

func SHA256Bytes

func SHA256Bytes(data []byte) string

SHA256Bytes is a convenience wrapper that hashes an in-memory byte slice.

func SHA256Hex

func SHA256Hex(r io.Reader) (string, error)

SHA256Hex reads r to EOF and returns the lowercase hex-encoded SHA-256 digest.

func ToPNG

func ToPNG(img image.Image) ([]byte, error)

ToPNG encodes img as a PNG and returns the raw bytes.

func VerifySHA256

func VerifySHA256(r io.Reader, expectedHex string) error

VerifySHA256 reads r to EOF, computes its SHA-256, and checks it against expectedHex (lowercase hex-encoded). Returns ErrChecksumMismatch on mismatch so callers can detect tampering or corruption.

Types

type FileType

type FileType string

FileType categorises the kind of file being handled.

const (
	FileTypeImage FileType = "image"
	FileTypePDF   FileType = "pdf"
)

type ImageConstraints

type ImageConstraints struct {
	MaxBytes  int64 // maximum file size in bytes; 0 = no limit
	MaxWidth  int   // 0 = no limit
	MaxHeight int   // 0 = no limit
	MinWidth  int   // 0 = no limit
	MinHeight int   // 0 = no limit
}

ImageConstraints defines size and pixel-dimension limits applied during image validation. Zero values mean "no limit" for dimension fields.

type ImageFormat

type ImageFormat string

ImageFormat is the source format detected from magic bytes.

const (
	FormatJPEG ImageFormat = "jpeg"
	FormatPNG  ImageFormat = "png"
	FormatGIF  ImageFormat = "gif"
	FormatWEBP ImageFormat = "webp"
	FormatBMP  ImageFormat = "bmp"
	FormatTIFF ImageFormat = "tiff"
)

type KeyParams

type KeyParams struct {
	// Tenant is the top-level namespace, typically a clinic UUID.
	Tenant string
	// Domain is the logical storage area within a tenant, e.g. "patients",
	// "reports", "avatars", "attachments".
	Domain string
	// UserID is the owner's identifier (member ID, patient ID, etc.).
	UserID string
	// Ext is the file extension including the leading dot, e.g. ".png", ".pdf".
	Ext string
}

KeyParams defines the structured components of an S3 object key.

The generated key layout is:

{Tenant}/{Domain}/{UserID}/{uuid}{Ext}

For example:

"3f2a1c.../patients/7b4d.../01928...uuid.png"

This structure makes it straightforward to list all files for a tenant, a domain within a tenant, or a specific user within a domain — and it ensures every presigned URL is naturally scoped to a single tenant/user pair.

type PDFConstraints

type PDFConstraints struct {
	MaxBytes int64 // maximum file size in bytes; 0 = no limit
}

PDFConstraints defines limits applied during PDF validation.

type ResizeOpts

type ResizeOpts struct {
	// Width and Height are the target dimensions in pixels.
	// If one is 0 it is derived from the other while preserving the aspect ratio.
	// Both must not be 0.
	Width  int
	Height int
	// Fit, when true, scales the image to fit within Width×Height while
	// preserving the aspect ratio (no cropping).  The resulting image may be
	// smaller than Width×Height on one axis.
	// When false, the image is scaled to exactly Width×Height (may distort).
	Fit bool
}

ResizeOpts controls how Resize scales an image.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL