在 POST 請求中使用表單上傳的檔案可以使用 Request 方法 getUploadedFiles()
擷取。
當使用 POST 請求上傳檔案時,請確定您的檔案上傳表單具有屬性 enctype="multipart/form-data"
,否則 getUploadedFiles()
會傳回一個空白陣列。
如果對相同的輸入名稱上傳多個檔案,請在 HTML 中的輸入名稱後加上方括號,否則 getUploadedFiles()
會只傳回輸入名稱的第一個已上傳檔案。
以下是包含單一和多重檔案上傳的範例 HTML 表單。
<!-- make sure the attribute enctype is set to multipart/form-data -->
<form method="post" enctype="multipart/form-data">
<!-- upload of a single file -->
<p>
<label>Add file (single): </label><br/>
<input type="file" name="example1"/>
</p>
<!-- multiple input fields for the same input name, use brackets -->
<p>
<label>Add files (up to 2): </label><br/>
<input type="file" name="example2[]"/><br/>
<input type="file" name="example2[]"/>
</p>
<!-- one file input field that allows multiple files to be uploaded, use brackets -->
<p>
<label>Add files (multiple): </label><br/>
<input type="file" name="example3[]" multiple="multiple"/>
</p>
<p>
<input type="submit"/>
</p>
</form>
已上傳的檔案可以使用 moveTo
方法移至目錄。以下是一個範例應用程式,用來處理上面 HTML 表單的已上傳檔案。
<?php
use DI\ContainerBuilder;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UploadedFileInterface;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$containerBuilder = new ContainerBuilder();
$container = $containerBuilder->build();
$container->set('upload_directory', __DIR__ . '/uploads');
AppFactory::setContainer($container);
$app = AppFactory::create();
$app->post('/', function (ServerRequestInterface $request, ResponseInterface $response) {
$directory = $this->get('upload_directory');
$uploadedFiles = $request->getUploadedFiles();
// handle single input with single file upload
$uploadedFile = $uploadedFiles['example1'];
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
$filename = moveUploadedFile($directory, $uploadedFile);
$response->getBody()->write('Uploaded: ' . $filename . '<br/>');
}
// handle multiple inputs with the same key
foreach ($uploadedFiles['example2'] as $uploadedFile) {
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
$filename = moveUploadedFile($directory, $uploadedFile);
$response->getBody()->write('Uploaded: ' . $filename . '<br/>');
}
}
// handle single input with multiple file uploads
foreach ($uploadedFiles['example3'] as $uploadedFile) {
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
$filename = moveUploadedFile($directory, $uploadedFile);
$response->getBody()->write('Uploaded: ' . $filename . '<br/>');
}
}
return $response;
});
/**
* Moves the uploaded file to the upload directory and assigns it a unique name
* to avoid overwriting an existing uploaded file.
*
* @param string $directory The directory to which the file is moved
* @param UploadedFileInterface $uploadedFile The file uploaded file to move
*
* @return string The filename of moved file
*/
function moveUploadedFile(string $directory, UploadedFileInterface $uploadedFile)
{
$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
// see https://php.dev.org.tw/manual/en/function.random-bytes.php
$basename = bin2hex(random_bytes(8));
$filename = sprintf('%s.%0.8s', $basename, $extension);
$uploadedFile->moveTo($directory . DIRECTORY_SEPARATOR . $filename);
return $filename;
}
$app->run();