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.
Is there a reason you wanted to do the uploading without splitting?
Splitting the file can be slow, especially if it’s large, plus requires additional HDD space etc.
It just seems ugly overall as well.
Pingback: Another way for PHP to use curl to transfer files-1024programmer