I'm trying to upload a file to an API, that requires a multipart form upload.
I don't want to store the file locally (I read it from an S3 bucket using flysystem) but I can'get it to work (always get a 422 error).
When I store the file locally first, it works:
// $filecontent is data from Flysystem
$fileContent = $this->documentStorage->read('remote filename.pdf');
file_put_contents(__DIR__.'/test.pdf', $fileContent);
$fileHandle = fopen(__DIR__.'/test.pdf', 'rb');
$params = [
'body' => [
'bestand' => $fileHandle
],
];
$response = $this->createClient()->request('POST', $url, $params);
I tried skipping the local save with a php://memory
and php://temp
stream, but that won't work:
$stream = fopen('php://temp', 'rb+');
fwrite($stream, $fileContent);
rewind($stream);
$params = [
'body' => [
'bestand' => $stream
],
];
$response = $this->createClient()->request('POST', $url, $params);
Tried manually making a multipart form, also doesn't work:
$dp = new DataPart($fileContent);
$formData = new FormDataPart(['bestand' => $dp]);
$preparedHeaders = $formData->getPreparedHeaders();
$params = [
'body' => $formData->bodyToString(),
'headers' => [
trim($preparedHeaders->toString())
],
];
$response = $this->createClient()->request('POST', $url, $params);
In a project I have, I use this approach, taking advantage of the "data" wrapper:
$fileName = 'some_random_file.mp3';
$fileContents = file_get_contents($fileName);
$fileHandle = fopen('data://text/plain;base64,' . base64_encode($fileContents), 'rb+');
stream_context_set_option($fileHandle, 'http', 'filename', $fileName);
stream_context_set_option($fileHandle, 'http', 'content_type', 'audio/mpeg');
$response = $this->httpClient
->request('POST', 'http://localhost:8000/upload/file',
[
'headers' => [
'Content-Type' => 'multipart/form-data'
],
'body' => [
'file' => $fileHandle,
],
]);