I search the few posts that were related on this forum but they appeared to have diverged down a different path. Here are my related methods for attempting to create a POST request that uploads a file that is local.
The request does indeed get made. However, the file does not seem to get added to the request. If I analyze the $request object before handling the request, the file upload information is 100% there.
I had tried that before with withUploadedFiles and it’s still was not working the files are never sent with the request. I retested and that is still the case. The request happens but $_FILES is empty.
Using a local file path may use more memory but it should still work. I figure that I could try to switch to using a Stream once I can get the file to upload at all.
This is not a bug, but correct and the purpose of the test because when you run tests, you simulate the request without a real webserver environment. When you use the PSR-7 request object only (and no $_FILES in your code) everything should work.
This makes sense. I was only doing a var_dump on $_FILES to see if it had contents in the request. I am using UploadManager. It supports file chunking. have you used this before? Do you have a better recommendation?
$uploadManager = new UploadManager($args['property']);
$uploadManager->afterUpload(function ($chunk) use ($args, &$object) {
$filepath = $chunk->getSavePath() . $chunk->getNameWithExtension();
if ($chunk->hasError() && file_exists($filepath)) {
// remove current chunk on error
return unlink($filepath);
}
});
$uploadManager->upload($this->config->tmpDir);
So I do see the file data under $request->getUploadedFiles() so it looks like I need to redo my upload code. Any clues on how to support file chunking with a PSR-7 request?
You need to manage individual chunks, assemble them in the correct order, and handle potential issues like missing or duplicated chunks.
Your chunked upload handler may also depend on the HTTP protocol, whether you use HTTP 1.1 or HTTP/2. Because chunked transfer encoding is not supported in HTTP/2, which provides its own mechanisms for data streaming.
The RFC 9112 (formerly known as RFC 7230) section 7.1 specifies the use of the Transfer-Encoding: chunked header in HTTP/1.1 for chunked transfer coding. This is a way to send a resource in chunks, possibly before knowing the total size of the resource.
Below is a basic example of how you could implement the handling of HTTP/1.1 requests with “chunked” Transfer-Encoding.
$app->post('/upload-chunked', function (ServerRequestInterface $request, ResponseInterface $response) {
$transferEncoding = $request->getHeaderLine('Transfer-Encoding');
$filename = $request->getHeaderLine('X-File-Name');
if (empty($filename)) {
$response = $response->withStatus(400);
$response->getBody()->write('Bad Request: Filename is required');
return $response;
}
if ($transferEncoding !== 'chunked') {
$response = $response->withStatus(400);
$response->getBody()->write('Bad Request: Expected chunked Transfer-Encoding');
return $response;
}
// Prepare the temp file to which the chunks will be written
$tempPath = __DIR__ . '/temp/' . $filename . '.part';
$tempFile = fopen($tempPath, 'ab');
$input = $request->getBody();
while (!$input->eof()) {
$chunkHeader = trim($input->readLine());
$chunkSize = hexdec($chunkHeader);
if ($chunkSize === 0) {
break;
}
$chunkData = $input->read($chunkSize);
fwrite($tempFile, $chunkData);
$input->read(2); // Skip the trailing CRLF after the chunk
}
fclose($tempFile);
$response->getBody()->write("Successfully received chunked data, stored in {$tempPath}.");
return $response;
});
Note that this is a simplified example and does not cover many aspects you would want to handle in a real-world application, such as error handling, validations, etc.