PHP 8.1: Curl: File uploads from strings with CURLStringFile
PHP Curl extension supports making HTTP(s) requests with file uploads. Since PHP 5.5, PHP Curl extension provides a CURLFile
class that accepts a URI or a path to a file, a mime type, and a file name to upload it as.
With CURLFile
class, it accepts a path or a URI, and not the contents itself. For files already stored on disk or any other stream, using CURLFile
class is quite straight-forward:
$txt_curlfile = new \CURLFile('test.txt', 'text/plain', 'test.txt');
$ch = curl_init('http://example.com/upload.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $txt_curlfile]);
curl_exec($ch);
Using CURLFile
was difficult if the file being uploaded is already stored in the memory, or not written to disk. It was possible to use data://
URIs with Base64 encoding, but it was not straight forward.
$txt = 'test content';
$txt_file = 'data://application/octet-stream;base64,' . base64_encode($txt);
$txt_curlfile = new \CURLFile($txt_file, 'text/plain', 'test.txt');
$ch = curl_init('http://example.com/upload.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $txt_curlfile]);
curl_exec($ch);
From PHP 8.1 and later, Curl extension has a new CURLStringFile
class, that works similar to CURLFile
class, but accepts the contents of the file instead of a path or a URI.
$txt = 'test content';
$txt_curlfile = new \CURLStringFile($txt, 'text/plain', 'test.txt');
$ch = curl_init('http://example.com/upload.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $txt_curlfile]);
curl_exec($ch);
The new CURLStringFile
class makes it easy to make a Curl file upload request using data that is already stored in memory. Some example use cases include uploading an image that PHP processes and is stored in a PHP variable, a processed XML file, or a PDF file generated from a PHP library.
CURLStringFile
class synopsis
class CURLStringFile {
public string $data;
public string $postname;
public string $mime;
public function __construct(string $data, string $postname, string $mime = "application/octet-stream") {}
}
- Unlike
CURLFile
class,CURLStringFile
class objects allow serializing and unserializing. CURLStringFile
objects can be clone. This is true forCURLFile
instances as well.CURLStringFile
class enforces typed properties. It is not allowed to set values other thanstring
values.
CURLStringFile
Polyfill
Curl extension treats CURLFile
class objects as a file upload, and it treats the same way for all classes that extend CURLFile
.
Taking advantage of that, it is possible to create a polyfill for CURLStringFile
.
class CURLStringFile extends CURLFile {
public function __construct(string $data, string $postname, string $mime = "application/octet-stream") {
$this->name = 'data://'. $mime .';base64,' . base64_encode($data);
$this->mime = $mime;
$this->postname = $postname;
}
}
Internally, the polyfilled CURLStringFile
class behaves exactly same as a CURLFile
class with a data://
URI, but it is not handled inside CURLStringFile::__construct
hiding the complexity, and working as a polyfill.
The polyfill above should work in all PHP versions >= 7.0.
Backwards Compatibility Impact
CURLStringFile
is a new class from the Curl extension, and it will not be possible to use it in PHP versions older than PHP 8.1. However, it is possible to polyfill this class to older PHP versions.