Build multipart/form-data in PHP
/** | |
* Build multipart/form-data | |
* | |
* @param array @$data Data | |
* @param array @$files 1-D array of files where key is field name and value if file contents | |
* @param string &$contentType Retun variable for content type | |
* | |
* @return string Encoded data | |
*/ | |
function buildMultipartFormData(array &$data, array &$files, &$contentType) | |
{ | |
$eol = "\r\n"; | |
// Build test string | |
$testStr = ''; | |
array_walk_recursive($data, function($item, $key) use (&$testStr, &$eol) { | |
$testStr .= $key . $eol . $item . $eol; | |
}); | |
// Get file content type and content. Add to test string | |
$finfo = finfo_open(FILEINFO_MIME_TYPE); | |
$fileContent = array(); | |
$fileContentTypes = array(); | |
foreach ($files as $key=>$filename) | |
{ | |
$fileContent[$key] = file_get_contents($filename); | |
$fileContentTypes[$key] = finfo_file($finfo, $filename); | |
$testStr .= $key . $eol . $fileContentTypes[$key] . $eol. $fileContent[$key] . $eol; | |
} | |
finfo_close($finfo); | |
// Find a boundary not present in the test string | |
$boundaryLen = 6; | |
$alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | |
do { | |
$boundary = '--'; | |
for ($i = 0; $i < $boundaryLen; $i++) | |
{ | |
$c = rand(0, 61); | |
$boundary .= $alpha[$c]; | |
} | |
// Check test string | |
if (strpos($testStr, $boundary) !== false) | |
{ | |
$boundary = null; | |
$boundaryLen++; | |
} | |
} while ($boundary === null); | |
unset($testStr); | |
// Set content type | |
$contentType = 'multipart/form-data, boundary='.$boundary; | |
// Build data | |
$rtn = ''; | |
$func = function($data, $baseKey = null) use (&$func, &$boundary, &$eol) | |
{ | |
$rtn = ''; | |
foreach ($data as $key=>&$value) | |
{ | |
// Get key | |
$key = $baseKey === null ? $key : ($baseKey . '[' . $key . ']'); | |
// Add data | |
if (is_array($value)) | |
$rtn .= $func($value, $key); | |
else | |
$rtn .= '--' . $boundary . $eol . 'Content-Disposition: form-data; name="'.$key.'"' . $eol . $eol . $value . $eol; | |
} | |
return $rtn; | |
}; | |
$rtn = $func($data); | |
// Add files | |
foreach ($files as $key=>$filename) | |
{ | |
$rtn .= '--' . $boundary . $eol . 'Content-Disposition: file; name="'.$key.'"; filename="'.basename($filename).'"' . $eol | |
. 'Content-Type: ' . $fileContentTypes[$key] . $eol | |
. 'Content-Transfer-Encoding: binary' . $eol . $eol | |
. $fileContent[$key] . $eol; | |
} | |
return $rtn . '--' . $boundary . '--' . $eol; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment