Well, I haven’t posted here in quite some time… I’m not dead, and don’t plan on completely ditching this blog, but well…
Anyway, onto the article.
I had a PHP application where I wanted to upload part of a large file to some other server. The naive method may be to simply split the file and upload through cURL, however I wanted to do this without any splitting. So I needed a way to send a POST request, being able to build the request body on the fly (note, you’ll need to know the total size to be able to send the Content-Length
header)
The obvious decision would be to use sockets rather than cURL, but I felt like seeing if it was possible with cURL anyway. Although I’ll still probably use sockets (because it’s easier in the end), I thought this might (well, not really) be useful to one of the three readers I get every month.
Anyway, if you look at the curl_setopt documentation, you’ll see a CURLOPT_READFUNCTION
constant, however, how to really use it doesn’t seem clear (especially with the boundaries for multipart/form-data encoding type). Also, the documentation is wrong.
Without further ado, here’s some sample code:
<?php $boundary = '-----------------------------168279961491'; // our request body $str = "$boundary\r\nContent-Disposition: form-data; name='how_do_i_turn_you'\r\n\r\non\r\n$boundary--\r\n"; // set up cURL $ch=curl_init('http://example.com/'); curl_setopt_array($ch, array( CURLOPT_HEADER => false, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => array( // we need to send these two headers 'Content-Type: multipart/form-data; boundary='.$boundary, 'Content-Length: '.strlen($str) ), // note, do not set the CURLOPT_POSTFIELDS setting CURLOPT_READFUNCTION => 'myfunc' )); // function to stream data // I'm not sure what the file pointer $fp does in this context // but $ch is the cURL resource handle, and $len is how many bytes to read function myfunc($ch, $fp, $len) { static $pos=0; // keep track of position global $str; // set data $data = substr($str, $pos, $len); // increment $pos $pos += strlen($data); // return the data to send in the request return $data; } // execute request, and show output for lolz echo curl_exec($ch); curl_close($ch);
Hopefully the comments give you enough idea how it all works.