I realise I can do this with CURL very easily, but I was wondering if it was possible to use file_get_contents()
with the http stream context to upload a file to a remote web server, and if so, how?
First of all, the first rule of multipart
Content-Type is to define a boundary that will be used as a delimiter between each part (because as the name says, it can have multiple parts). The boundary can be any string that is not contained in the content body. I will usually use a timestamp:
define('MULTIPART_BOUNDARY', '--------------------------'.microtime(true));
Once your boundary is defined, you must send it with the Content-Type
header to tell the webserver what delimiter to expect:
$header = 'Content-Type: multipart/form-data; boundary='.MULTIPART_BOUNDARY;
Once that is done, you must build a proper content body that matches the HTTP specification and the header you sent. As you know, when POSTing a file from a form, you will usually have a form field name. We'll define it:
// equivalent to <input type="file" name="uploaded_file"/> define('FORM_FIELD', 'uploaded_file');
Then we build the content body:
$filename = "/path/to/uploaded/file.zip"; $file_contents = file_get_contents($filename); $content = "--".MULTIPART_BOUNDARY."\r\n". "Content-Disposition: form-data; name=\"".FORM_FIELD."\"; filename=\"".basename($filename)."\"\r\n". "Content-Type: application/zip\r\n\r\n". $file_contents."\r\n"; // add some POST fields to the request too: $_POST['foo'] = 'bar' $content .= "--".MULTIPART_BOUNDARY."\r\n". "Content-Disposition: form-data; name=\"foo\"\r\n\r\n". "bar\r\n"; // signal end of request (note the trailing "--") $content .= "--".MULTIPART_BOUNDARY."--\r\n";
As you can see, we're sending the Content-Disposition
header with the form-data
disposition, along with the name
parameter (the form field name) and the filename
parameter (the original filename). It is also important to send the Content-Type
header with the proper MIME type, if you want to correctly populate the $_FILES[]['type']
thingy.
If you had multiple files to upload, you just repeat the process with the $content bit, with of course, a different FORM_FIELD
for each file.
Now, build the context:
$context = stream_context_create(array( 'http' => array( 'method' => 'POST', 'header' => $header, 'content' => $content, ) ));
And execute:
file_get_contents('http://url/to/upload/handler', false, $context);
NOTE: There is no need to encode your binary file before sending it. HTTP can handle binary just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With