# `Multipart`
[🔗](https://github.com/breakroom/multipart/blob/v0.6.1/lib/multipart.ex#L1)

`Multipart` constructs multipart messages.

It aims to produce multipart messages that are compatible with [RFC
2046](https://tools.ietf.org/html/rfc2046#section-5.1) for general use, and
[RFC 7578](https://tools.ietf.org/html/rfc7578) for constructing
`multipart/form-data` requests.

# `t`

```elixir
@type t() :: %Multipart{boundary: String.t(), parts: [Multipart.Part.t()]}
```

# `add_part`

```elixir
@spec add_part(t(), Multipart.Part.t()) :: t()
```

Adds a part to the `Multipart` message.

# `body_binary`

```elixir
@spec body_binary(t()) :: binary()
```

Returns a binary of the `Multipart` message body.

This uses `body_stream/1` under the hood.

# `body_stream`

```elixir
@spec body_stream(t()) :: Enum.t()
```

Returns a `Stream` of the `Multipart` message body.

# `content_length`

```elixir
@spec content_length(t()) :: pos_integer()
```

Returns the length of the `Multipart` message in bytes.

It uses the `content_length` property in each of the message parts to
calculate the length of the multipart message without reading the entire
body into memory. `content_length` is set on the `Multipart.Part` by the
constructor functions when possible, such as when the in-memory binary
or the file on disk can be inspected.

This will throw an error if any of the parts does not have `content_length`
defined.

# `content_type`

```elixir
@spec content_type(t(), String.t(), Keyword.t()) :: String.t()
```

Returns the Content-Type header for the `Multipart` message.

Pass in `Keyword` option `:quote_boundary` set `false` to disable quoting the boundary.

    iex> multipart = Multipart.new("abc123")
    iex> Multipart.content_type(multipart, "multipart/mixed")
    "multipart/mixed; boundary=\"abc123\""
    iex> Multipart.content_type(multipart, "multipart/mixed", quote_boundary: false)
    "multipart/mixed; boundary=abc123"

# `new`

```elixir
@spec new(String.t()) :: t()
```

Create a new `Multipart` request.

Pass in the boundary as the first argument to set it explicitly, otherwise
it will default to a random 16 character alphanumeric string padded by `==`
on either side.

The boundary must conform to the RFC 2046 boundary grammar (1-70 of the
allowed `bcharsnospace` characters); anything else raises `ArgumentError`.
The default boundary is a 128-bit random token, so it is safe against a part
body that happens to contain the boundary. If you supply a custom boundary
you are responsible for ensuring it cannot appear in any part body.

---

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