bardiir
bardiir

Reputation: 14784

cURL file uploads not working anymore after upgrade from PHP 5.5 to 5.6

I've got a cURL upload that fails after upgrading from PHP 5.5 to 5.6:

$aPost = array(
    'file' => "@".$localFile,
    'default_file' => 'html_version.html',
    'expiration' => (2*31*24*60*60)
)

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);

The file seems to be empty on the target system.

Upvotes: 30

Views: 30803

Answers (4)

Lion
Lion

Reputation: 17879

CURLOPT_SAFE_UPLOAD was deprecated in PHP 7 and newer versions. Using it will throw an exception (verified on PHP 8), because it got removed:

NOTICE: PHP message: PHP Fatal error: Uncaught ValueError: curl_setopt(): Disabling safe uploads is no longer supported

In the documentation there is a notice, that this is always true. Unfortunately, no information that it was removed and how you should handle file uploads instead. PHP has CURLFile for this. The following example works on PHP 8:

$file = new CURLFile($path, 'image/png', $name);
$data = array('tags' => 'example-of-other-form-fields','file' => $file);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://my-image-hoster.com/api.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
var_dump($header, $body);
  • $path is the local path on the file system, where the file you want to upload is located.
  • $name sets the image name in the HTTP POST form. The server can use this name. For example, when the target server uses PHP too, you'll get it from $_FILES['file']['name']
  • Since http multipart/form-data supports more fields as well, you can pass more to the $data array. The (php) server will find them in $_POST like $_POST['tags'] in my example
  • I also fetch the header and body from curl, because it makes much sense to get some response like the link to the uploaded image. By checking the header, it may indicates errors by non 200 status codes

Upvotes: 1

Deepti Gehlot
Deepti Gehlot

Reputation: 617

Just do following changes for PHP 5.5 or greater

Instead of "@" . $localFile just use new CurlFile($localFile)

And set

curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);

Upvotes: 32

Simhachalam Gulla
Simhachalam Gulla

Reputation: 996

Include a runtime check to make your code compatible with lower versions too like below

$aPost = array(
    'default_file' => 'html_version.html',
    'expiration' => (2*31*24*60*60)
)
if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
    $aPost['file'] = new CURLFile($localFile);
    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
} else {
    $aPost['file'] = "@".$localFile;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);

Upvotes: 10

bardiir
bardiir

Reputation: 14784

Actually I found the answer while starting the question. There is a new Variable included with curl in PHP 5.5: CURLOPT_SAFE_UPLOAD this is set to false by default in PHP 5.5 and is switched to a default of true in PHP 5.6.

This will prevent the '@' upload modifier from working for security reasons - user input could contain malicious upload requests. You can use the CURLFile class to upload files while CURLOPT_SAFE_UPLOAD is set to true or (if you're sure your variables are safe you can switch the CURLOPT_SAFE_UPLOAD to false manually):

 curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);

Here's a source for the information that got me searching in the right direction: http://comments.gmane.org/gmane.comp.php.devel/87521

It's mentioned in the changed functions too: http://php.net/manual/en/migration56.changed-functions.php But not in the backward incompatible changes, really tripped me off...

Upvotes: 42

Related Questions