{"id":51770,"date":"2015-10-04T19:39:54","date_gmt":"2015-10-04T19:39:54","guid":{"rendered":"http:\/\/barrycarlyon.co.uk\/wordpress\/?p=51770"},"modified":"2015-10-04T19:39:54","modified_gmt":"2015-10-04T19:39:54","slug":"php5-6-curl-and-file-uploads","status":"publish","type":"post","link":"https:\/\/barrycarlyon.co.uk\/wordpress\/2015\/10\/04\/php5-6-curl-and-file-uploads\/","title":{"rendered":"PHP5.6+ cURL and file uploads"},"content":{"rendered":"<p>Came across something odd today, and thought I&#8217;d condense down my Tweets on the subject into a blog post.<\/p>\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\">\n<p lang=\"en\" dir=\"ltr\">Hmm I have a PHP cURL that won&#39;t post a file with @ odd\u2026 Need to investigate later\u2026<\/p>\n<p>&mdash; Barry Carlyon (@BarryCarlyon) <a href=\"https:\/\/twitter.com\/BarryCarlyon\/status\/650623366534041600?ref_src=twsrc%5Etfw\">October 4, 2015<\/a><\/p><\/blockquote>\n<p><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<p>Basically, I use cURL and some wacky wacky stuff to upload files to a site over HTTP POST. And since I&#8217;d just grabbed PHP 7 from HomeBrew, it had overridden my PHP 5.5 install that comes as <i>standard<\/i> on OSX 10.10 and thus I cross checked the script with my MacPorts PHP 5.6 install and found the same. (Yes THREE different PHP versions for science&#8230;)<\/p>\n<p>&#8220;Traditionally&#8221; the method for this would be something along the lines of:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\r\n    $ch = curl_init('SOMEURL');\r\n    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);\r\n    curl_setopt($ch, CURLOPT_POST, true);\r\n    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/35.0.1916.153 Safari\/537.36');\r\n\r\n    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\r\n\r\n    $data = array(\r\n        'some_file' =&gt; '@' . $some_path\r\n    );\r\n    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);\r\n\r\n    $r = curl_exec($ch);\r\n    curl_close($ch);\r\n\r\n<\/pre>\n<p>On PHP 5.5 and previous that works file, using a <strong>@<\/strong> at the start of a POST entry would instruct PHP\/cURL to treat the data\/string as a File Path to Upload.<\/p>\n<p>This behaviour is controlled by the PHP cURL constant of <strong>CURLOPT_SAFE_UPLOAD<\/strong>. In PHP 5.6 this constant changed from default <strong>FALSE<\/strong> to default <strong>TRUE<\/strong>, setting to <strong>TRUE<\/strong> means that a string starting <strong>@<\/strong> is treated as a String and not a File Path to upload. The changes are documented on the <a href=\"http:\/\/php.net\/curl_setopt\">PHP.net website<\/a>, but the primary trip up is that <i>most<\/i> of us just use the defaults and we get tripped up when things change.<\/p>\n<p>So, after trying to set this to <strong>FALSE<\/strong> under PHP 5.6 it <i>still<\/i> wasn&#8217;t working, and under PHP 7 you are thrown an error to indicate that you are not allowed to change this constant any more for security reasons, which is fine.<\/p>\n<p>The solution is to use the <a href=\"http:\/\/php.net\/manual\/en\/class.curlfile.php\">CURLFile class<\/a>, which is pretty straightforward:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\r\n    $ch = curl_init('SOMEURL');\r\n    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);\r\n    curl_setopt($ch, CURLOPT_POST, true);\r\n    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/35.0.1916.153 Safari\/537.36');\r\n\r\n    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\r\n\r\n    $data = array(\r\n        'some_file' =&gt; new CURLFile($some_path)\r\n    );\r\n    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);\r\n\r\n    $r = curl_exec($ch);\r\n    curl_close($ch);\r\n\r\n<\/pre>\n<p>This is the <i>truly lazy edition<\/i>, just chuck a <strong>new CURLFile($path)<\/strong> at it, instead of the <strong>@<\/strong>. I&#8217;m sure <strong>CURLFile<\/strong> does more useful stuff, but this was enough to get me back up and running!<\/p>\n<p>Thus endeth this blog post!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Came across something odd today, and thought I&#8217;d condense down my Tweets on the subject into a blog post. Hmm I have a PHP cURL that won&#39;t post a file with @ odd\u2026 Need to investigate later\u2026 &mdash; Barry Carlyon (@BarryCarlyon) October 4, 2015 Basically, I use cURL and some wacky wacky stuff to upload &hellip; <a href=\"https:\/\/barrycarlyon.co.uk\/wordpress\/2015\/10\/04\/php5-6-curl-and-file-uploads\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;PHP5.6+ cURL and file uploads&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[88,45],"tags":[82,86,84,335],"class_list":["post-51770","post","type-post","status-publish","format-standard","hentry","category-code-geekery","category-geekery","tag-code","tag-curl","tag-php","tag-uploading-files"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts\/51770","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/comments?post=51770"}],"version-history":[{"count":7,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts\/51770\/revisions"}],"predecessor-version":[{"id":51777,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts\/51770\/revisions\/51777"}],"wp:attachment":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/media?parent=51770"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/categories?post=51770"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/tags?post=51770"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}