Reputation: 14784
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
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']
$data
array. The (php) server will find them in $_POST
like $_POST['tags']
in my exampleUpvotes: 1
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
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
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