PHP 5.0 ~ 5.6 Compatibility cURL File Upload Function Example Analysis

  • 2021-09-24 21:53:38
  • OfStack

This paper analyzes the compatibility of cURL file uploading function between PHP 5.0 and 5.6. Share it for your reference, as follows:

One requirement made recently is to call cURL through PHP and upload files in multipart/form-data format. Step on a few pits, enough for one article.

Important warning

Don't read the official Chinese document of PHP! The version can't keep up with you!

Differences of cURL between different versions of PHP

PHP supports cURL by giving CURL_POSTFIELDS Pass an associative array instead of a string to generate multipart/form-data POST request for.

Traditionally, cURL of PHP supports attaching files to array data using the syntax of "@ + file full path" for cURL to read and upload. This is similar to the syntax of calling cURL program directly from the command line:


curl_setopt(ch, CURLOPT_POSTFIELDS, array(
  'file' => '@'.realpath('image.png'),
));

equals


$ curl -F "file=@/absolute/path/to/image.png" <url>

However, PHP introduced a new CURLFile class from 5.5 to point to files. The CURLFile class can also define in detail the MIME type, file name, and other additional information that may appear in the multipart/form-data data. PHP recommends using CURLFile instead of the old @ Syntax:


curl_setopt(ch, CURLOPT_POSTFIELDS, [
  'file' => new CURLFile(realpath('image.png')),
]);

PHP 5.5 Additionally introduces CURL_SAFE_UPLOAD Option, you can force the cURL module of PHP to reject the old @ Syntax, only CURLFile files are accepted. The default value for 5.5 is false, and the default value for 5.6 is true.

But one point of the pit is: @ The syntax was typed deprecated in 5.5 and deleted directly in 5.6 (which produces ErorException: The usage of the) @filename API for file uploading is deprecated. Please use the CURLFile class instead).

For PHP 5.6 +, manually set CURL_SAFE_UPLOAD For false is meaningless. It is not literally understood that "setting to false can open the old unsafe way"-the old way has completely disappeared as an obsolete syntax. PHP 5.6 + = = CURLFile only, don't have any illusions.

My deployment environment is 5.4 (@ syntax only), but my development environment is 5.6 (CURLFile only). Neither of them is pressed on 5.5, a transitional version that supports both. As a result, two sets of code with environmental judgments must be written.

Now the problem comes...

Environmental Judgment: Beware of magic numbers!

I've seen the code for this environmental judgment:


if (version_compare(phpversion(), '5.4.0') >= 0)

My evaluation of this code is only one word: shit.

This judgment falls into the typical magic number trap. The version number appears inexplicably in the code, and it is difficult to understand which function change the author is stuck with without checking the PHP manual and update history for half a day.

Code should return to its original source. Our actual demand is actually: CURLFile will be adopted first, and there will be no degradation to tradition @ Grammar. Then the code comes:


if (class_exists('\CURLFile')) {
  $field = array('fieldname' => new \CURLFile(realpath($filepath)));
} else {
  $field = array('fieldname' => '@' . realpath($filepath));
}

Explicitly specified degradation options are recommended

From a reliable point of view, it is recommended to specify CURL_SAFE_UPLOAD Explicitly tells php whether to tolerate or prohibit the old @ Grammar. Note that in the lower version of PHP, CURLOPT_SAFE_UPLOAD The constant itself may not exist and needs to be judged:


if (class_exists('\CURLFile')) {
  curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
} else {
  if (defined('CURLOPT_SAFE_UPLOAD')) {
    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
  }
}

cURL Option Setting Order

Whether it is curl_setopt() Single shot or curl_setopt_array() Batch, the options of cURL are always set to take effect, and the set options will immediately affect the behavior of cURL when setting subsequent options.

For example CURLOPT_SAFE_UPLOAD Just with CURLOPT_POSTFIELDS The behavior of. If you set the CURLOPT_POSTFIELDS Reset CURLOPT_SAFE_UPLOAD , then the binding effect of the latter will not take effect. Because when setting the former, cURL has already finished the actual reading of the data!

There are several options in cURL that have such pits, so be careful. Fortunately, there are not many options for this kind of "dependency relationship", and the mechanism is not complicated, so it can be handled simply. My method is to set all the options in batch first, and then until curl_exec() It was only used at the first moment of curl_setopt() Single shot setting CURLOPT_POSTFIELDS .

Actually curl_setopt_array() In the array used by the CURLOPT_POSTFIELDS The position in the back is also reliable. The associative arrays of PHP are order-guaranteed, and we can also assume that curl_setopt_array() The internal execution order 1 must be in order from beginning to end (well, I know assume is not a good thing, but some facts are too simple, so let me make a minimum assertion), so you can rest assured.

My approach is just to add a redundant insurance on the code performance, highlighting the importance of order to prevent later hands from being cheap.

Namespace

PHP versions 5.2 or below do not have namespaces. Spatial separators are used in the code \ A parser error is thrown. To take care of PHP 5.2 is actually easy to think of, just give up the namespace.

Note instead that PHP 5.3 + has a namespace. Whether calling CURLFile or using class_exists() To judge the existence of CURLFile, it is recommended to write as \CURLFile Explicitly specify the top-level space to prevent code from collapsing when wrapped in the namespace.

For more readers interested in PHP related content, please check the topics on this site: "php curl Usage Summary", "PHP Network Programming Skills Summary", "PHP Array (Array) Operation Skills Encyclopedia", "php String (string) Usage Summary", "PHP Data Structure and Algorithm Tutorial", "php Programming Algorithm Summary" and "PHP Operation and Operator Usage Summary"

I hope this paper is helpful to everyone's PHP programming.


Related articles: