Using cURL and PHP to upload files through a form post

Lately I have been working on a project that requires me to use PHP to interact with a REST based service. cURL is the logical choice for making HTTP calls to the REST service.

I love cURL, I’ve blogged about it before, but I recently ran into some major issues.

The REST service I was using required me to send two files along with some meta information. easy enough. I used the following code:

$postFields = array();
 
//files
$postFields['file'] = "@$filePath";
$postFields['thumbnail'] = "@$thumbnailPath";
 
//metaData
$postFields['title'] = "$title";
$postFields['description'] = "$description";
$postFields['tags'] = "$tags";
$postFields['licenseinfo'] = "$licenseinfo";
$postFields['token'] = "$userToken";
 
$curl_handle = curl_init();
 
curl_setopt($curl_handle, CURLOPT_URL, $api_url);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_POST, true);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $http_post_fields);
 
//execute the API Call
$returned_data = curl_exec($curl_handle);

The code worked great, sending an “at” sign (@) before the file path makes sure that cURL sends the file as part of a “multipart/form-data” post. Exactly what we needed.

The form post from cURL worked great, but the REST service was retuning a 400 error and saying “The specified thumbnail file is not supported.”. I was at a loss. The service documentation stated the “jpg, jpeg, gif, and png” files were supported.

I ended up contacting the developers of the service who told me that the content type for the file had to be set to “image/jpg” (for jpg).

After pouring through the cURL documentation and not finding anything about how to set the content type for a single file in a “multipart/form-data” post, I turned to Goolge. My searches with about as helpful as the cURL docs. I sent a few hours hacking my code and trying some things, I ever read some posts from 2008 saying that is was not possible to do. Then, I got a break through, a single ray of light. On a message board was a single sentence replay. “You should try this… $image;type=image/jpg”.

That was the break through I needed. Below is final updated code:

$postFields = array(); 
 
//files
 $postFields['file'] = "@$filePath";
 
//get the extension of the image file
$tumbnailExtention = preg_replace('/^.*\.([^.]+)$/D', '$1', $thumbnailPath);
$postFields['thumbnail'] = "@$thumbnailPath;type=image/$tumbnailExtention";
 
//metaData
$postFields['title'] = "$title";
$postFields['description'] = "$description";
$postFields['tags'] = "$tags";
$postFields['licenseinfo'] = "$licenseinfo";
$postFields['token'] = "$userToken"; 
 
$curl_handle = curl_init();
 
curl_setopt($curl_handle, CURLOPT_URL, $api_url);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_POST, true);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $http_post_fields); 
 
//execute the API Call
$returned_data = curl_exec($curl_handle);

In summary, if you need to set the content type of a file being sent an image through cURL, via a POST, use the following format:
$postFields[‘file’] = “@PATHTOFILE;type=CONTENTTYPEHERE”;

UITextField.text is not always there!

If you have UITextField in your app and you want to validate a value or  see is there something in it you might think to write some code like this:

if (![addNewCellTextField.text isEqualToString:@""])

You would be right, but this will fail if the field is never touched! When a user taps the field, and it gets focus, UITextField.text = nil. That means that the condition above would be true, thats not what we want at all!

But once the UITextField is touched, the value becomes an instance of NSString with value of @””.  So make sure that you write your code to check for the nil case, like this:

if (addNewCellTextField.text != nil && ![addNewCellTextField.text isEqualToString:@""])