PHP 8.0环境下多文件上传遭遇三类错误求助(含Undefined array key等)
Hey Julia, let's break down those three foreach()-related errors you're hitting and fix them step by step. The root issues come from a misconfigured HTML form and missing validation checks in your PHP code—let's sort this out.
Why You're Seeing These Errors
foreach() argument must be of type array|object: Your form isn't set up correctly to send files to the server, so$_FILES["userfile"]ends up beingnullor not an array when you try to loop over it.Undefined array key/Trying to access array offset on value of type null: PHP 8.0 enforces strict checks for undefined array keys and null offsets (unlike older versions that ignored them). Without validation, you're trying to access keys that don't exist when no files are selected or uploads fail.
Step 1: Fix the HTML Form
Your current HTML has critical flaws that prevent file uploads from working properly:
enctype="multipart/form-data"needs to be on the<form>tag (not a<div>) to enable file transfers.- You're missing the
method="post"attribute—file uploads require POST requests. - Duplicate
idattributes on file inputs are invalid HTML.
Here's the corrected HTML:
<form method="post" enctype="multipart/form-data"> <label>Selecione as fotos de hoje aqui: <input id="image-file-1" type="file" name="userfile[]"> <input id="image-file-2" type="file" name="userfile[]"> </label> <button type="submit">Enviar Fotos</button> </form>
Step 2: Secure & Validated PHP Code
We'll add strict checks to handle edge cases (like no files selected or single-file uploads) and comply with PHP 8.0's stricter error handling. We'll also add security measures to prevent common upload issues.
Here's the revised PHP code:
// First, confirm the form was submitted and files exist if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['userfile'])) { $uploadDir = "../www/layout/diario_de_obra/upload_img/"; // Create upload directory if it doesn't exist if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } // Normalize files array to handle both single and multi-file uploads $files = is_array($_FILES['userfile']['tmp_name']) ? $_FILES['userfile'] : [ 'tmp_name' => [$_FILES['userfile']['tmp_name']], 'name' => [$_FILES['userfile']['name']], 'error' => [$_FILES['userfile']['error']] ]; // Loop through each uploaded file foreach ($files['tmp_name'] as $key => $tmpName) { // Skip files that failed to upload if ($files['error'][$key] !== UPLOAD_ERR_OK) { echo "Erro ao enviar " . $files['name'][$key] . ": Código de erro " . $files['error'][$key] . "<br>"; continue; } $fileName = basename($files['name'][$key]); // Sanitize filename to block path attacks $destination = $uploadDir . $fileName; // Move the file to the target directory if (move_uploaded_file($tmpName, $destination)) { print($fileName . " enviado com sucesso!<br>"); } else { print("Falha ao enviar " . $fileName . "<br>"); } } } else { echo "Nenhum arquivo foi enviado ou o formulário não foi submetido corretamente."; }
Key Improvements Explained
- Form Validation: We first check if the request is a POST and if
$_FILES['userfile']exists to avoid processing invalid requests. - Directory Check: Ensures the upload folder exists (and creates it if needed) to prevent
move_uploaded_filefailures. - Normalized Files Array: Handles both single and multi-file uploads so the
foreachloop works consistently. - Upload Error Handling: Skips files that failed to upload (e.g., too large, invalid type) instead of trying to process broken data.
- Filename Sanitization: Uses
basename()to block path traversal attacks, a critical security step for file uploads.
These changes should eliminate all three errors you're seeing and make your upload code more robust and secure.
内容的提问来源于stack exchange,提问作者Julia

