Skip to content

Instantly share code, notes, and snippets.

@iansltx
Created May 2, 2015 03:31
Show Gist options
  • Star 33 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save iansltx/a6ed41d19852adf2e496 to your computer and use it in GitHub Desktop.
Save iansltx/a6ed41d19852adf2e496 to your computer and use it in GitHub Desktop.
Multipart file uploads in PHP from strings
<?php
/**
* PHP's curl extension won't let you pass in strings as multipart file upload bodies; you
* have to direct it at an existing file (either with deprecated @ syntax or the CURLFile
* type). You can use php://temp to get around this for one file, but if you want to upload
* multiple files then you've got a bit more work.
*
* This function manually constructs the multipart request body from strings and injects it
* into the supplied curl handle, with no need to touch the file system.
*
* @param $ch resource curl handle
* @param $boundary string a unique string to use for the each multipart boundary
* @param $fields string[] fields to be sent as fields rather than files, as key-value pairs
* @param $files string[] fields to be sent as files, as key-value pairs
* @return resource the curl handle with request body, and content type set
* @see http://stackoverflow.com/a/3086055/2476827 was what I used as the basis for this
**/
function buildMultiPartRequest($ch, $boundary, $fields, $files) {
$delimiter = '-------------' . $boundary;
$data = '';
foreach ($fields as $name => $content) {
$data .= "--" . $delimiter . "\r\n"
. 'Content-Disposition: form-data; name="' . $name . "\"\r\n\r\n"
. $content . "\r\n";
}
foreach ($files as $name => $content) {
$data .= "--" . $delimiter . "\r\n"
. 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . "\r\n\r\n"
. $content . "\r\n";
}
$data .= "--" . $delimiter . "--\r\n";
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: multipart/form-data; boundary=' . $delimiter,
'Content-Length: ' . strlen($data)
],
CURLOPT_POSTFIELDS => $data
]);
return $ch;
}
// and here's how you'd use it
$ch = curl_init('http://httpbin.org/post');
$ch = buildMultiPartRequest($ch, uniqid(),
['key' => 'value', 'key2' => 'value2'], ['somefile' => 'contents!', 'someotherfile' => 'yoloswag']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($ch);
@nguyenbathanh
Copy link

nguyenbathanh commented Jan 24, 2017

Thank you.
Your script is really helpful.

@JohnFDoucette
Copy link

Fantastic posts.
Thank you.
Works very well.

@robtimus
Copy link

I found this when searching for a streaming multipart/form-data solution for cURL. Because I couldn't find any I wrote my own: https://packagist.org/packages/robtimus/multipart. This works like the above code but doesn't put everything in memory; it uses cURLs read function instead.

@fhefh2015
Copy link

I found this when searching for a streaming multipart/form-data solution for cURL. Because I couldn't find any I wrote my own: https://packagist.org/packages/robtimus/multipart. This works like the above code but doesn't put everything in memory; it uses cURLs read function instead.

wonderful

@S-eddin
Copy link

S-eddin commented Aug 15, 2020

thank you man it works well

@kilingzhang
Copy link

thx !

@NoName-Ninja
Copy link

Hello! I still have an issue of files not uploading. example of my file array ['files' => 'contents!', 'files' => 'yoloswag']

@DiegoFleitas
Copy link

Hello! I still have an issue of files not uploading. example of my file array ['files' => 'contents!', 'files' => 'yoloswag']

This is old. The smartest solution is using a composer package that adjusts to your requirements ex: https://packagist.org/packages/riverline/multipart-parser
If you still want a quick and dirty solution chatgpt might do just that if you give it the original script

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment