How to send “multipart/related” content type in PHP How to send “multipart/related” content type in PHP curl curl

How to send “multipart/related” content type in PHP


per https://stackoverflow.com/a/25998544/1067003 , libcurl has no built-in mechanism to encode requests as multipart/related (and this guy is the author and main developer of curl, so he'd know) meaning that you have to encode the body yourself.

i don't have access to a server to test on, but i think it would go something like this:

<?phpdeclare(strict_types = 1);$files = array (        new MultipartRelatedFile ( 'foo.php' ),        new MultipartRelatedFile ( 'bar.php' ),        new MultipartRelatedFile ( 'baz.php' ) );$body = generateMultipartRelatedBody ( $files, $boundary );$ch = curl_init ();curl_setopt_array ( $ch, array (        CURLOPT_HTTPHEADER => array (                'Content-Type: multipart/related; boundary="' . $boundary.'"'         ),        CURLOPT_POST => true,        CURLOPT_POSTFIELDS => $body,        CURLOPT_URL => 'http://127.0.0.1:9999' ) );curl_exec ( $ch );class MultipartRelatedFile {    public $path;    public $postname;    public $content_type;    function __construct(string $path) {        if (! is_readable ( $path )) {            throw new \Exception ( 'file is not readable!' );        }        $this->path = $path;        $this->content_type = mime_content_type ( $path );        $this->postname = basename ( $path );    }}/** * generate http body for a multipart/related POST request * * @param MultipartRelatedFile[] $files * @param string|null $boundary */function generateMultipartRelatedBody(array $files, string &$boundary = NULL): string {    if (null === $boundary) {        $boundary = bin2hex ( random_bytes ( 10 ) );    }    $n = "\r\n";    $body = '';    foreach ( $files as $file ) {        $body .= $boundary . $n;        $body .= 'Content-Disposition: attachment; filename=' . $file->postname . $n;        $body .= "Content-Type: " . $file->content_type . $n;        $body .= $n . file_get_contents ( $file->path ) . $n;    }    $body .= $boundary . '--';    return $body;}

warning: short of making sure it looks correct-ish in a netcat server, this is untested code.i'd also like to point out that the specs doesn't mention any Content-Length header, and implies that Content-Id is optional if the filename is provided in some other way (like in Content-Disposition) AND the start header is not used.in any case, specs can be found here: https://tools.ietf.org/html/rfc2112

edit: forgot to add quotes (") around the boundary of the initial Content-Type header, fixed.