{"id":20741096,"url":"https://github.com/robtimus/php-multipart","last_synced_at":"2025-04-24T02:53:48.463Z","repository":{"id":60774669,"uuid":"154996381","full_name":"robtimus/php-multipart","owner":"robtimus","description":"A library to support (streaming) multiparts","archived":false,"fork":false,"pushed_at":"2025-02-28T20:09:30.000Z","size":159,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-24T02:53:42.670Z","etag":null,"topics":["multipart","multipart-formdata","multipart-uploads","php"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/robtimus/multipart","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robtimus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-27T18:27:55.000Z","updated_at":"2025-02-28T20:08:51.000Z","dependencies_parsed_at":"2024-01-20T14:22:18.180Z","dependency_job_id":"63f61e4a-4e6a-49ba-8221-3149295a26f1","html_url":"https://github.com/robtimus/php-multipart","commit_stats":{"total_commits":46,"total_committers":1,"mean_commits":46.0,"dds":0.0,"last_synced_commit":"5cff9002a9e0c120e8fb25f677161284ef229a9e"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fphp-multipart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fphp-multipart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fphp-multipart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robtimus%2Fphp-multipart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robtimus","download_url":"https://codeload.github.com/robtimus/php-multipart/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250552038,"owners_count":21449162,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["multipart","multipart-formdata","multipart-uploads","php"],"created_at":"2024-11-17T06:33:46.916Z","updated_at":"2025-04-24T02:53:48.437Z","avatar_url":"https://github.com/robtimus.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multipart\n[![Packagist Version](https://img.shields.io/packagist/v/robtimus/multipart)](https://packagist.org/packages/robtimus/multipart)\n[![Build Status](https://github.com/robtimus/data-url/actions/workflows/build.yml/badge.svg)](https://github.com/robtimus/php-multipart/actions/workflows/build.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=robtimus%3Amultipart\u0026metric=alert_status)](https://sonarcloud.io/summary/overall?id=robtimus%3Amultipart)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=robtimus%3Amultipart\u0026metric=coverage)](https://sonarcloud.io/summary/overall?id=robtimus%3Amultipart)\n\nA library to support (streaming) multiparts.\n\n## Supported multipart types\n\n### multipart/form-data\n\nTo 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:\n\n* `addValue($name, $value)` adds a string value with the given name. Both arguments are required.\n* `addFile($name, $filename, $content, $contentType, $contentLength = -1)` adds a file with the given name. The name, filename, [content](#multipart-content) and content type are required; the content length is optional, and will be ignored if the content is a string.\n\nAn example:\n\n    // the multipart object can take an optional pre-existing boundary\n    $multipart = new MultipartFormData();\n    $multipart-\u003eaddValue('name', 'Rob');\n    $multipart-\u003eaddFile('file', 'file.txt', 'Hello World', 'text/plain');\n    $multipart-\u003efinish();\n\n#### Multiple values or files with the same parameter name\n\n`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.\n\nPHP 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:\n\n    $multipart = new MultipartFormData();\n    $multipart-\u003eaddValue('name', 'Rob');\n    $multipart-\u003eaddFile('file[]', 'file.txt', 'Hello World', 'text/plain');\n    $multipart-\u003eaddFile('file[]', 'file.html', '\u003chtml\u003eHello World\u003c/html\u003e', 'text/html');\n    $multipart-\u003efinish();\n\n### multipart/related\n\nTo 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:\n\n* `addPart($content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part without a content disposition. This should be used for the root part. The [content](#multipart-content) and content type are required; the content length is optional, and will be ignored if the content is a string; the content transfer encoding is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.\n* `addInlineFile($contentID, $filename, $content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds an inline file. The content ID, filename, [content](#multipart-content) and content type are required; the content length is optional, and will be ignored if the content is a string; the content transfer encoding is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.\n\nAn example:\n\n    // the multipart object can take an optional pre-existing boundary\n    $multipart = new MultipartRelated();\n    $multipart-\u003eaddPart(file_get_contents('body.html'), 'text/html');\n    // the content length is irrelevant because the content is a string\n    $multipart-\u003eaddInlineFile('logo', 'logo.png', base64_encode(file_get_contents('logo.png')), 'image/png', -1, 'base64');\n    $multipart-\u003efinish();\n\nTo use this inline file in the HTML body, use `cid:logo` as the source of an image.\n\n### multipart/alternative\n\nTo create a multipart/alternative object, create a `MultipartAlternative` instance, add the alternatives, and call `finish()`. There are two methods for adding alternatives:\n\n* `addMultipart(Multipart $multipart)` adds another multipart as alternative. This is most often used with a multipart/related object.\n* `addPart($content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part with the given content. The [content](#multipart-content) and content type are required; the content length is optional, and will be ignored if the content is a string; the content transfer encoding is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.\n\nAn example:\n\n    // the multipart object can take an optional pre-existing boundary\n    $multipart = new MultipartAlternative();\n    // $related is a MultipartRelated instance as created above\n    $multipart-\u003eaddPart(file_get_contents('body.txt'), 'text/plain');\n    $multipart-\u003eaddMultipart($related);\n    $multipart-\u003efinish();\n\n### multipart/mixed\n\nTo create a multipart/mixed object, create a `MultipartMixed` instance, add the parts, and call `finish()`. There are three methods for adding parts:\n\n* `addMultipart(Multipart $multipart)` adds another multipart. This is most often used with a multipart/alternative or multipart/related object.\n* `addPart($content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part with the given content. This can be used for the bodies of plain text emails. The [content](#multipart-content) and content type are required; the content length is optional, and will be ignored if the content is a string; the content transfer encoding is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.\n* `addAttachment($filename, $content, $contentType, $contentLength = -1, $contentTransferEncoding = '')` adds a part with content disposition `attachment`. The filename, [content](#multipart-content) and content type are required; the content length is optional, and will be ignored if the content is a string; the content transfer encoding is optional, and will be used for the `Content-Transfer-Encoding` header if it is set.\n\nAn example:\n\n    // the multipart object can take an optional pre-existing boundary\n    $multipart = new MultipartMixed();\n    // $alternative is a MultipartAlternative instance as created above\n    $multipart-\u003eaddMultipart($alternative);\n    // the content length is irrelevant because the content is a string\n    $multipart-\u003eaddFile('file.png', base64_encode(file_get_contents('file.png')), 'image/png', -1, 'base64');\n    $multipart-\u003efinish();\n\n## Multipart content\n\nThe content of a part or file can be given in one of three ways:\n\n* As a string. The content length will be ignored.\n* As a resource that can be read using `fread`. It is up to the caller to close this resource.\n* 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.\n\nExamples, using a `MultipartFormData` object:\n\n    // content length is not necessary\n    $multipart-\u003eaddFile('file1', 'file.txt', 'Hello World', 'text/plain');\n\n    // make sure to close the resource after the request has been sent\n    $resource = fopen('file.html');\n    $multipart-\u003eaddFile('file.html', $resource, 'text/html', filesize('file.html'));\n\n    // assume that class MyResource exists and has a function read($length)\n    $myResource = new MyResource(...);\n    $multipart-\u003eaddFile('file.bin', array($myResource, 'read'), 'application/octet-stream');\n\n## cURL support\n\nTo send a multipart object with a cURL request, you need to follow some steps:\n\n* Set the request type using `CURLOPT_CUSTOMREQUEST`.\n* Set the `CURLOPT_UPLOAD` option to `true`.\n* Set the object's `curl_read` method as the `CURLOPT_READFUNCTION`.\n* Make sure the `Content-Type` and `Content-Length` headers are set. Note that the `Content-Length` header is optional.\n\nFor instance:\n\n    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');\n    curl_setopt($ch, CURLOPT_UPLOAD, true);\n    curl_setopt($ch, CURLOPT_READFUNCTION, array($multipart, 'curl_read'));\n    \n    $headers = ['Content-Type: ' . $multipart-\u003egetContentType()];\n    $contentLength = $multipart-\u003egetContentLength();\n    if ($contentLength \u003e= 0) {\n        $headers[] = 'Content-Length: ' .  $contentLength;\n    }\n    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);\n\n## Non-streaming support\n\nIf 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 `curl_read`), otherwise the buffered contents may not contain all desired contents (especially if you're using resources or callables).\n\n`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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtimus%2Fphp-multipart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobtimus%2Fphp-multipart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtimus%2Fphp-multipart/lists"}