# `PhoenixKit.Modules.Storage.File`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.95/lib/modules/storage/schemas/file.ex#L1)

Schema for original file uploads.

Represents the original uploaded file with metadata. Each file can have multiple
instances (variants) like thumbnails, resizes, or video quality variants.

## File Types

- **image** - JPEG, PNG, WebP, GIF, HEIC (scalable)
- **video** - MP4, WebM, MOV, AVI, MKV (scalable)
- **document** - PDF, DOC, DOCX, TXT, MD (non-scalable)
- **archive** - ZIP, RAR, 7Z, TAR, GZ (non-scalable)

## Status Flow

- `processing` - File is being processed (variants being generated)
- `active` - File is ready and available
- `failed` - Processing failed

## Fields

- `original_file_name` - User's original filename
- `file_name` - System filename (uuid_v7-original.ext)
- `mime_type` - MIME type (image/jpeg, video/mp4, etc.)
- `file_type` - High-level type (image, video, document, archive)
- `ext` - File extension (jpg, mp4, pdf, etc.)
- `file_checksum` - SHA256 hash of file content for integrity verification
- `user_file_checksum` - SHA256 hash of (user_uuid + file_checksum) for per-user deduplication
- `size` - File size in bytes
- `width` - Image/video width in pixels (nullable)
- `height` - Image/video height in pixels (nullable)
- `duration` - Video duration in seconds (nullable)
- `status` - Processing status
- `metadata` - JSONB with EXIF, codec info, etc.
- `user_uuid` - Owner of the file

## Examples

    # Image file
    %File{
      id: "018e3c4a-9f6b-7890-abcd-ef1234567890",
      original_file_name: "profile.jpg",
      file_name: "018e3c4a-9f6b-7890-original.jpg",
      mime_type: "image/jpeg",
      file_type: "image",
      ext: "jpg",
      file_checksum: "abc123def456...",
      user_file_checksum: "xyz789ghi012...",
      size: 524_288,  # 512 KB
      width: 2000,
      height: 2000,
      status: "active",
      metadata: %{"camera" => "Canon EOS"},
      user_uuid: "018e3c4a-1234-5678-abcd-ef1234567890"
    }

    # Video file
    %File{
      original_file_name: "intro.mp4",
      file_name: "018e3c4a-9f6b-7890-original.mp4",
      mime_type: "video/mp4",
      file_type: "video",
      ext: "mp4",
      file_checksum: "def456ghi789...",
      user_file_checksum: "mno345pqr678...",
      size: 10_485_760,  # 10 MB
      width: 1920,
      height: 1080,
      duration: 30,  # 30 seconds
      status: "processing",
      metadata: %{"codec" => "h264"}
    }

    # Document file
    %File{
      original_file_name: "report.pdf",
      file_name: "018e3c4a-9f6b-7890-original.pdf",
      mime_type: "application/pdf",
      file_type: "document",
      ext: "pdf",
      file_checksum: "ghi789jkl012...",
      user_file_checksum: "stu901vwx234...",
      size: 2_097_152,  # 2 MB
      status: "active"
    }

# `t`

```elixir
@type t() :: %PhoenixKit.Modules.Storage.File{
  __meta__: term(),
  duration: integer() | nil,
  ext: String.t(),
  file_checksum: String.t(),
  file_name: String.t(),
  file_path: String.t() | nil,
  file_type: String.t(),
  folder: term(),
  folder_links: term(),
  folder_uuid: UUIDv7.t() | nil,
  height: integer() | nil,
  inserted_at: DateTime.t() | nil,
  instances:
    [PhoenixKit.Modules.Storage.FileInstance.t()]
    | Ecto.Association.NotLoaded.t(),
  metadata: map() | nil,
  mime_type: String.t(),
  original_file_name: String.t(),
  size: integer(),
  status: String.t(),
  updated_at: DateTime.t() | nil,
  user: PhoenixKit.Users.Auth.User.t() | Ecto.Association.NotLoaded.t(),
  user_file_checksum: String.t(),
  user_uuid: UUIDv7.t(),
  uuid: UUIDv7.t() | nil,
  width: integer() | nil
}
```

# `archive?`

Returns whether this file is an archive.

# `changeset`

Changeset for creating or updating a file.

## Required Fields

- `original_file_name`
- `file_name`
- `mime_type`
- `file_type` (must be: "image", "video", "document", "archive")
- `ext`
- `file_checksum`
- `user_file_checksum`
- `size`
- `user_uuid`

## Validation Rules

- File type must be valid
- Status must be valid (processing, active, failed)
- Size must be positive
- Width/height must be positive (if provided)
- Duration must be positive (if provided)

# `document?`

Returns whether this file is a document.

# `image?`

Returns whether this file is an image.

# `scalable?`

Returns whether this file type supports variant generation (scalable).

# `video?`

Returns whether this file is a video.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
