PHPackages                             robtimus/multipart - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. robtimus/multipart

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

robtimus/multipart
==================

A library to support creating (streaming) multiparts

2.0(2mo ago)14953.7k—0.8%6Apache-2.0PHPPHP &gt;=8.0CI passing

Since Oct 27Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/robtimus/php-multipart)[ Packagist](https://packagist.org/packages/robtimus/multipart)[ Docs](https://github.com/robtimus/php-multipart)[ RSS](/packages/robtimus-multipart/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (1)Versions (5)Used By (6)

Multipart
=========

[](#multipart)

[![Packagist Version](https://camo.githubusercontent.com/cc7ea23fae4c966992dbd44a5646076186be5c236acad9322e6e253ef387b89f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f6274696d75732f6d756c746970617274)](https://packagist.org/packages/robtimus/multipart)[![Build Status](https://github.com/robtimus/data-url/actions/workflows/build.yml/badge.svg)](https://github.com/robtimus/php-multipart/actions/workflows/build.yml)[![Quality Gate Status](https://camo.githubusercontent.com/e666953556175bb12491d89206ed5abdf9d9a770e1217b279479f87c6c57af78/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d726f6274696d75732533416d756c746970617274266d65747269633d616c6572745f737461747573)](https://sonarcloud.io/summary/overall?id=robtimus%3Amultipart)[![Coverage](https://camo.githubusercontent.com/f5fb77aed1ea1da3bf25222066142dcc1ab8820267a5105ef30413530dcf9fb2/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d726f6274696d75732533416d756c746970617274266d65747269633d636f766572616765)](https://sonarcloud.io/summary/overall?id=robtimus%3Amultipart)

A library to support creating (streaming) multiparts.

Supported multipart types
-------------------------

[](#supported-multipart-types)

### multipart/form-data

[](#multipartform-data)

To create a multipart/form-data object, create a `MultipartFormData` instance, add the form fields, and call `finish()`. There are two methods for adding form fields:

- `addValue($name, $value, $contentType = '', $contentTransferEncoding = '')` adds a string value with the given name.
    - `$name` and `$value` are required.
    - `$contentType` is optional, and will be used for the `Content-Type` header if it is set. It should be set if the implicit content type should not be `text/plain`.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.
- `addFile($name, $filename, $content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a file with the given name.
    - `$name`, `$filename`, [`$content`](#multipart-content) and `$contentType` are required.
    - `$contentLength` is optional, and will be ignored if the content is a string.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.

An example:

```
// the multipart object can take an optional pre-existing boundary
$multipart = new MultipartFormData();
$multipart->addValue('name', 'Rob');
$multipart->addFile('file', 'file.txt', 'Hello World', 'text/plain');
// add a content type to a non-file part
$multipart->addValue('json', '{"id": 1}', contentType: 'application/json')
$multipart->finish();
```

#### Multiple values or files with the same parameter name

[](#multiple-values-or-files-with-the-same-parameter-name)

`MultipartFormData` follows [RFC 7578](https://tools.ietf.org/html/rfc7578), and not [RFC 2388](https://tools.ietf.org/html/rfc2388). This means that multiple values or files with the same parameter name are not sent with a multipart/mixed field but instead as separate parts.

PHP servers require multiple values or files to be sent with a name that ends with `[]`. Because `MultipartFormData` is written to support also other server types that do not have this requirement, it is up to the caller to add these. For instance:

```
$multipart = new MultipartFormData();
$multipart->addValue('name', 'Rob');
$multipart->addFile('file[]', 'file.txt', 'Hello World', 'text/plain');
$multipart->addFile('file[]', 'file.html', 'Hello World', 'text/html');
$multipart->finish();
```

### multipart/related

[](#multipartrelated)

To create a multipart/related object, create a `MultipartRelated` instance, add the root part and any inline files, and call `finish()`. There are two methods for adding parts:

- `addPart($content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part without a content disposition. This should be used for the root part.
    - [`$content`](#multipart-content) and `$contentType` are required.
    - `$contentLength` is optional, and will be ignored if the content is a string.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.
- `addInlineFile($contentID, $filename, $content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds an inline file.
    - `$contentID`, `$filename`, [`$content`](#multipart-content) and `$contentType` are required.
    - `$contentLength` is optional, and will be ignored if the content is a string.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.

An example:

```
// the multipart object can take an optional pre-existing boundary
$multipart = new MultipartRelated();
$multipart->addPart(file_get_contents('body.html'), 'text/html');
// the content length is irrelevant because the content is a string
// the content transfer encoding needs to be set to base64
$multipart->addInlineFile('logo', 'logo.png', base64_encode(file_get_contents('logo.png')), 'image/png', contentTransferEncoding: 'base64');
$multipart->finish();
```

To use this inline file in the HTML body, use `cid:logo` as the source of an image.

### multipart/alternative

[](#multipartalternative)

To create a multipart/alternative object, create a `MultipartAlternative` instance, add the alternatives, and call `finish()`. There are two methods for adding alternatives:

- `addMultipart(Multipart $multipart)` adds another multipart as alternative. This is most often used with a multipart/related object.
- `addPart($content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part with the given content.
    - [`$content`](#multipart-content) and `$contentType` are required.
    - `$contentLength` is optional, and will be ignored if the content is a string.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.

An example:

```
// the multipart object can take an optional pre-existing boundary
$multipart = new MultipartAlternative();
// $related is a MultipartRelated instance as created above
$multipart->addPart(file_get_contents('body.txt'), 'text/plain');
$multipart->addMultipart($related);
$multipart->finish();
```

### multipart/mixed

[](#multipartmixed)

To create a multipart/mixed object, create a `MultipartMixed` instance, add the parts, and call `finish()`. There are three methods for adding parts:

- `addMultipart(Multipart $multipart)` adds another multipart. This is most often used with a multipart/alternative or multipart/related object.
- `addPart($content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part with the given content. This can be used for the bodies of plain text emails.
    - [`$content`](#multipart-content) and `$contentType` are required.
    - `$contentLength` is optional, and will be ignored if the content is a string.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.
- `addAttachment($filename, $content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part with content disposition `attachment`.
    - `$filename`, [`$content`](#multipart-content) and `$contentType` are required.
    - `$contentLength` is optional, and will be ignored if the content is a string.
    - `contentTransferEncoding` is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.

An example:

```
// the multipart object can take an optional pre-existing boundary
$multipart = new MultipartMixed();
// $alternative is a MultipartAlternative instance as created above
$multipart->addMultipart($alternative);
// the content length is irrelevant because the content is a string
// the content transfer encoding needs to be set to base64
$multipart->addFile('file.png', base64_encode(file_get_contents('file.png')), 'image/png', contentTransferEncoding: 'base64');
$multipart->finish();
```

Multipart content
-----------------

[](#multipart-content)

The content of a part or file can be given in one of three ways:

- As a string. The content length will be ignored.
- As a resource that can be read using `fread`. It is up to the caller to close this resource.
- As a callable that takes a length, and returns a string that is not larger than the given length. If there is nothing more to read it should return the empty string.

Examples, using a `MultipartFormData` object:

```
// content length is not necessary
$multipart->addFile('file1', 'file.txt', 'Hello World', 'text/plain');

// make sure to close the resource after the request has been sent
$resource = fopen('file.html');
$multipart->addFile('file.html', $resource, 'text/html', filesize('file.html'));

// assume that class MyResource exists and has a function read($length)
$myResource = new MyResource(...);
$multipart->addFile('file.bin', array($myResource, 'read'), 'application/octet-stream');
```

cURL support
------------

[](#curl-support)

To send a multipart object with a cURL request, you need to follow some steps:

- Set the request type using `CURLOPT_CUSTOMREQUEST`.
- Set the `CURLOPT_UPLOAD` option to `true`.
- Set the object's `curlRead` method as the `CURLOPT_READFUNCTION`.
- Make sure the `Content-Type` and `Content-Length` headers are set. Note that the `Content-Length` header is optional.

For instance:

```
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_setopt($ch, CURLOPT_READFUNCTION, array($multipart, 'curlRead'));

$headers = ['Content-Type: ' . $multipart->getContentType()];
$contentLength = $multipart->getContentLength();
if ($contentLength >= 0) {
    $headers[] = 'Content-Length: ' .  $contentLength;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
```

Non-streaming support
---------------------

[](#non-streaming-support)

If streaming is not possible (e.g. because a string is required, like in the `mail` function), you can buffer a multipart object in-memory by calling the `buffer` method. This method takes an optional buffer size, and returns the buffered contents. The content length will be set accordingly. Note that you should do this before calling `read` (or `curlRead`), otherwise the buffered contents may not contain all desired contents (especially if you're using resources or callables).

`Multipart.__toString()` has been overridden to buffer the multipart object as well, so you can achieve the same by casting a multipart object to `string`. The difference is that `buffer` requires the multipart object to be finished.

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance83

Actively maintained with recent releases

Popularity45

Moderate usage in the ecosystem

Community17

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 98.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~890 days

Total

4

Last Release

89d ago

Major Versions

1.x-dev → 2.02026-02-18

PHP version history (2 changes)1.0PHP &gt;=5.4

2.0PHP &gt;=8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/ae572a8816c41da92fcdc2c0f6296dde938ffc0bd81a99225ad3be6e057483de?d=identicon)[robtimus](/maintainers/robtimus)

---

Top Contributors

[![robtimus](https://avatars.githubusercontent.com/u/7405731?v=4)](https://github.com/robtimus "robtimus (79 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

multipartmultipart-formdatamultipart-uploadsphpstreamingmultipart

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/robtimus-multipart/health.svg)

```
[![Health](https://phpackages.com/badges/robtimus-multipart/health.svg)](https://phpackages.com/packages/robtimus-multipart)
```

###  Alternatives

[alexandre-daubois/lazy-stream

Write data to streams, only when it is really needed to.

755.7k](/packages/alexandre-daubois-lazy-stream)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
