PhoenixKitPhotos.Zip (PhoenixKit Photos v0.3.0)

Copy Markdown View Source

A ZIP archive written front to back, for answering a download while the files are still being read: nothing is ever seeked back to, so it goes straight into a chunked response.

Files are stored, not compressed: photos and videos are compressed already, and deflating them costs a lot of CPU to save almost nothing. ZIP64 records appear only when a size or an offset needs them, so an ordinary archive opens in everything, and one of 40 GB still works.

Each file is measured before it is written (add/5), which is why the headers can carry the real sizes and need no data descriptors. That is also what makes a file that cannot be read harmless: {:error, {:read, reason}} means nothing of it was written and the archive can go on. {:error, {:write, reason}} means it cannot: stop, and do not finish/1, so what the reader has is plainly broken rather than quietly short.

Summary

Functions

Adds the file at path as name, sending the bytes through write, a function of iodata that answers :ok or {:error, reason}. time is the file's date, a DateTime or nil.

Adds a small text as a file, for a note about the archive itself.

The part of the archive that comes after the files.

An empty archive.

Types

t()

@type t() :: %PhoenixKitPhotos.Zip{entries: list(), offset: non_neg_integer()}

Functions

add(zip, name, path, time, write)

@spec add(t(), String.t(), Path.t(), DateTime.t() | nil, (iodata() ->
                                                      :ok | {:error, term()})) ::
  {:ok, t()} | {:error, {:read | :write, term()}}

Adds the file at path as name, sending the bytes through write, a function of iodata that answers :ok or {:error, reason}. time is the file's date, a DateTime or nil.

add_text(zip, name, text, write)

@spec add_text(t(), String.t(), iodata(), (iodata() -> :ok | {:error, term()})) ::
  {:ok, t()} | {:error, {:write, term()}}

Adds a small text as a file, for a note about the archive itself.

finish(zip)

@spec finish(t()) :: iodata()

The part of the archive that comes after the files.

new()

@spec new() :: t()

An empty archive.