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 ¶
- Receive multipart file from the HTTP handler (r io.Reader, size int64).
- Call ValidateImage / ValidatePDF to check magic bytes and size.
- For images: call ProcessImage to decode any supported format, optionally resize, and re-encode as PNG.
- Call files.New(cfg).UploadImage / UploadPDF to store in S3 with an integrity-verified checksum and a structured key.
- Persist the returned key; use AccessURLForUser to generate time-limited presigned GET links that enforce tenant/user ownership.
Index ¶
- Variables
- func DecodeImage(r io.Reader, format ImageFormat) (image.Image, error)
- func Dimensions(r io.Reader, format ImageFormat) (width, height int, err error)
- func KeyBelongsTo(key, tenant, userID string) bool
- func KeyPrefix(tenant, domain, userID string) string
- func KeySegments(key string) (tenant, domain, userID, filename string, err error)
- func MD5Base64(r io.Reader) (string, error)
- func NewKey(p KeyParams) string
- func ProcessImage(r io.Reader, format ImageFormat, opts *ResizeOpts) ([]byte, error)
- func Resize(src image.Image, opts ResizeOpts) (image.Image, error)
- func SHA256Base64(r io.Reader) (string, error)
- func SHA256Bytes(data []byte) string
- func SHA256Hex(r io.Reader) (string, error)
- func ToPNG(img image.Image) ([]byte, error)
- func VerifySHA256(r io.Reader, expectedHex string) error
- type FileType
- type ImageConstraints
- type ImageFormat
- type KeyParams
- type PDFConstraints
- type ResizeOpts
Constants ¶
This section is empty.
Variables ¶
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.
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.
var DefaultPDFConstraints = PDFConstraints{
MaxBytes: 25 * 1024 * 1024,
}
DefaultPDFConstraints is a sensible default: 25 MB.
Functions ¶
func DecodeImage ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
Resize returns a new image scaled to the dimensions described by opts using high-quality Catmull-Rom resampling.
func SHA256Base64 ¶
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 ¶
SHA256Bytes is a convenience wrapper that hashes an in-memory byte slice.
Types ¶
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.