PHP 8.1.0 Beta 1 available for testing

The CURLFile class

(PHP 5 >= 5.5.0, PHP 7, PHP 8)


CURLFile should be used to upload a file with CURLOPT_POSTFIELDS.

Unserialization of CURLFile instances is not allowed. As of PHP 7.4.0, serialization is forbidden in the first place.

Class synopsis

CURLFile {
/* Properties */
public mixed $name;
public mixed $mime;
/* Methods */
public __construct(string $filename, ?string $mime_type = null, ?string $posted_filename = null)
public getFilename(): string
public getMimeType(): string
public getPostFilename(): string
public setMimeType(string $mime_type): void
public setPostFilename(string $posted_filename): void



Name of the file to be uploaded.


MIME type of the file (default is application/octet-stream).


The name of the file in the upload data (defaults to the name property).

See Also

Table of Contents

add a note add a note

User Contributed Notes 5 notes

7 years ago
There are "@" issue on multipart POST requests.

Solution for PHP 5.5 or later:
- Use CURLFile instead of "@".

Solution for PHP 5.4 or earlier:
- Build up multipart content body by youself.
- Change "Content-Type" header by yourself.

The following snippet will help you :D


* For safe multipart POST request for PHP5.3 ~ PHP 5.4.
* @param resource $ch cURL resource
* @param array $assoc "name => value"
* @param array $files "name => path"
* @return bool
function curl_custom_postfields($ch, array $assoc = array(), array $files = array()) {
// invalid characters for "name" and "filename"
static $disallow = array("\0", "\"", "\r", "\n");
// build normal parameters
foreach ($assoc as $k => $v) {
$k = str_replace($disallow, "_", $k);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"{$k}\"",
// build file parameters
foreach ($files as $k => $v) {
        switch (
true) {
false === $v = realpath(filter_var($v)):
            case !
            case !
// or return false, throw new InvalidArgumentException
$data = file_get_contents($v);
$v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v));
$k = str_replace($disallow, "_", $k);
$v = str_replace($disallow, "_", $v);
$body[] = implode("\r\n", array(
"Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"",
"Content-Type: application/octet-stream",
// generate safe boundary
do {
$boundary = "---------------------" . md5(mt_rand() . microtime());
    } while (
preg_grep("/{$boundary}/", $body));
// add boundary for each parameters
array_walk($body, function (&$part) use ($boundary) {
$part = "--{$boundary}\r\n{$part}";
// add final boundary
$body[] = "--{$boundary}--";
$body[] = "";
// set options
return @curl_setopt_array($ch, array(
CURLOPT_POST       => true,
CURLOPT_POSTFIELDS => implode("\r\n", $body),
"Expect: 100-continue",
"Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type

alin dot rzv at gmail dot com
6 years ago
i've seen some downvotes , here is a small example of using curl to upload image .



// Create a CURLFile object / procedural method
$cfile = curl_file_create('resource/test.png','image/png','testpic'); // try adding

// Create a CURLFile object / oop method
#$cfile = new CURLFile('resource/test.png','image/png','testpic'); // uncomment and use if the upper procedural method is not working.

// Assign POST data
$imgdata = array('myimage' => $cfile);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $target);
curl_setopt($curl, CURLOPT_USERAGENT,'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
curl_setopt($curl, CURLOPT_HTTPHEADER,array('User-Agent: Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15','Referer: http://someaddress.tld','Content-Type: multipart/form-data'));
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true); // enable posting
curl_setopt($curl, CURLOPT_POSTFIELDS, $imgdata); // post images
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // if any redirection after upload
$r = curl_exec($curl);

php at miknik dot co dot uk
3 years ago
Simple function to construct CURLFile from the file path:

function makeCurlFile($file){
$mime = mime_content_type($file);
$info = pathinfo($file);
$name = $info['basename'];
$output = new CURLFile($file, $mime, $name);
return $output;

Then construct an array of all the form fields you want to post. For each file upload just add the CURLFiles.

$ch = curl_init("");
$mp3 =makeCurlFile($audio);
$photo = makeCurlFile($picture);
$data = array('mp3' => $mp3, 'picture' => $photo, 'name' => 'My latest single', 'description' => 'Check out my newest song');
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
if (curl_errno($ch)) {
   $result = curl_error($ch);
curl_close ($ch);
ohcc at 163 dot com
3 years ago
This is how to upload two or more files at once with cURLFile.

With modern browser support, you can upload many files at one time if the multiple attribute is given.

<input type="file" name="file[]" muliple />

With outdated browser you can place many input elements to do that.

<input type="file" name="file[]" />
<input type="file" name="file[]" />
<input type="file" name="file[]" />

Here's the php code to handle multiple uploads.

= curl_init();
// ... more code ...
$postFields = array(
'file[0]' => new cURLFile($file1, $mimetype1, $basename1),
'file[1]' => new cURLFile($file2, $mimetype2, $basename2)
curl_setopt($cURLHandle, CURLOPT_POSTFIELDS, $fields);
// ... more code ...
Each file's mimetype can be determined by finfo, and its basename can be fetched from $_FILES if it is uploaded from the client-end or by pathinfo() if it is locally stored.

Don't leave the square brackets in ''file[0]'' empty like 'file[]', in that way only the last file will be received by the remote server.
humbads at gmail dot com
5 years ago
// For backward compatibility,
// convert @ prefixed file names to CurlFile class
// since @ prefix is deprecated as of PHP 5.6
if(is_array($postfields) == true)
    // Check each post field
    foreach($postfields as $key => $value)
        // Convert values for keys starting with '@' prefix
        if(strpos($value, '@') === 0)
            // Get the file name
            $filename = ltrim($value, '@');
            // Convert the value to the new class
            $postfields[$key] = new CURLFile($filename);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

This code should be extended if support for the ';type=mimetype' suffix is needed.
To Top