移动端相机拍摄图片无法通过联系表单上传的技术排查请求
移动端相机拍摄照片上传表单的异常问题
我是Web开发新手,现有一个联系表单:通过文件夹选择.jpg/.jpeg/.png等文件时可正常发送给接收方,但在移动端使用相机拍摄照片上传时,图片无法发送。JS验证会在发送前检查文件大小和类型,有问题则阻止提交。奇怪的是:部分新手机上,用户首次填写表单时拍摄的照片可发送,但同一用户用同一手机第二次填写时,图片无法发送。
相关代码
HTML代码
<div class="file-upload-container"> <!-- File Upload 1 --> <label for="fileUpload1" data-lang="contact-form-11">Bestand 1:</label> <input type="file" id="fileUpload1" name="fileUpload1" capture="environment" accept=".jpg, .jpeg, .png, .pdf, .doc, .docx"> <span id="fileUpload1Name"></span> <!-- Span to display the uploaded file name --> <!-- File Upload 2 --> <label for="fileUpload2" data-lang="contact-form-12">Bestand 2:</label> <input type="file" id="fileUpload2" name="fileUpload2" capture="environment" accept=".jpg, .jpeg, .png, .pdf, .doc, .docx"> <span id="fileUpload2Name"></span> <!-- Span to display the uploaded file name --> </div>
JS验证代码
function validateContactForm() { let naam = document.getElementById("name").value; let email = document.getElementById("email").value; let bericht = document.getElementById("message").value; let contactReasons = document.querySelectorAll('input[name="contact_reason"]'); let isValid = true; let errorMessage = ''; // Vorige foutmeldingen wissen document.getElementById("formInputErrorDisplay").innerHTML = ''; // Naam validatie if (naam.trim() === "") { errorMessage += getErrorMessage("naamRequired") + "<br>"; isValid = false; } // E-mail validatie let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { errorMessage += getErrorMessage("invalidEmail") + "<br>"; isValid = false; } // Bericht validatie if (bericht.trim().length < 100 || bericht.trim().length > 2500) { errorMessage += getErrorMessage("messageLength") + "<br>"; isValid = false; } // Radio buttons validatie let isReasonSelected = Array.from(contactReasons).some(radio => radio.checked); if (!isReasonSelected) { errorMessage += getErrorMessage("reasonRequired") + "<br>"; isValid = false; } // Bestanden validatie let bestandsGrootteLimiet = 5242880; // 5MB for (let i = 1; i <= 2; i++) { let fileUpload = document.getElementById(`fileUpload${i}`); if (fileUpload && fileUpload.files.length > 0) { let file = fileUpload.files[0]; if (file.size > bestandsGrootteLimiet) { errorMessage += getErrorMessage("fileTooLarge", {i}) + "<br>"; isValid = false; } if (!['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'].includes(file.type)) { errorMessage += getErrorMessage("invalidFileType", { i }) + "<br>"; isValid = false; } } } // Foutmeldingen weergeven in het div-element if (!isValid) { document.getElementById("formInputErrorDisplay").innerHTML = errorMessage; } return isValid; } // Event listener toevoegen aan het formulier document.getElementById("contact_form").addEventListener("submit", function(event) { if (!validateContactForm()) { event.preventDefault(); } });
PHP代码
// Bestandsverwerking en -upload for ($i = 1; $i <= 2; $i++) { $fileInputName = "fileUpload" . $i; if (isset($_FILES[$fileInputName]) && $_FILES[$fileInputName]['error'] == UPLOAD_ERR_OK) { // Bestandstype en -grootte validatie $allowedTypes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; $maxSize = 5 * 1024 * 1024; // 5 MB $fileType = $_FILES[$fileInputName]['type']; $fileSize = $_FILES[$fileInputName]['size']; if (!in_array($fileType, $allowedTypes) || $fileSize > $maxSize) { echo "Ongeldig bestandstype of bestandsgrootte voor bestand $i.<br>"; continue; } // Generate unique file name to prevent duplicates $fileExt = pathinfo($_FILES[$fileInputName]['name'], PATHINFO_EXTENSION); $newFileName = uniqid("upload_", true) . '.' . $fileExt; $target_dir = "../../../back-end/uploads/"; $target_file = $target_dir . $newFileName; // Bestandsupload if (move_uploaded_file($_FILES[$fileInputName]["tmp_name"], $target_file)) { $bestanden[] = $target_file; // Logboekbericht $logMessage = "[" . date("d-m-Y H:i:s") . "] Bestand geüpload: " . $newFileName . " door " . $email . ", Grootte: " . filesize($target_file) . " bytes\n"; writeToLog($logMessage, $email); } else { echo "Er was een probleem met het uploaden van bestand $i.<br>"; } } }
邮件发送使用最新版本的PHPMailer,请问我遗漏了什么?不知道下一步该如何排查。
排查方向与修复方案
1. 移动端相机照片的MIME类型不匹配
部分新手机拍摄的照片会使用image/heic、image/heif等非标准MIME类型,或者客户端传递的file.type不准确,导致JS和PHP的类型验证失败。
- JS端修复:同时校验文件后缀和MIME类型,做兜底判断:
// 替换原有文件类型验证逻辑 const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; const allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf', '.doc', '.docx']; const fileExt = '.' + file.name.split('.').pop().toLowerCase(); if (!allowedTypes.includes(file.type) && !allowedExtensions.includes(fileExt)) { errorMessage += getErrorMessage("invalidFileType", { i }) + "<br>"; isValid = false; }
- PHP端修复:用服务器端获取的真实MIME类型替代客户端传递的值,同时校验后缀:
// 替换原有的类型判断逻辑 $allowedTypes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; $allowedExtensions = ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx']; $fileExt = strtolower(pathinfo($_FILES[$fileInputName]['name'], PATHINFO_EXTENSION)); // 服务器端获取真实MIME类型 $fileType = mime_content_type($_FILES[$fileInputName]['tmp_name']); if (!in_array($fileType, $allowedTypes) || !in_array($fileExt, $allowedExtensions) || $fileSize > $maxSize) { echo "Ongeldig bestandstype of bestandsgrootte voor bestand $i.<br>"; continue; }
2. 表单未重置导致的文件输入缓存
用户第二次提交时,浏览器可能缓存了第一次的文件输入状态,导致fileUpload.files获取异常。
- 提交后重置表单:在表单提交成功后重置控件:
document.getElementById("contact_form").addEventListener("submit", function(event) { const formValid = validateContactForm(); if (!formValid) { event.preventDefault(); } else { // 提交成功后延迟重置,避免影响提交流程 setTimeout(() => { this.reset(); // 清空文件名显示 document.getElementById("fileUpload1Name").textContent = ""; document.getElementById("fileUpload2Name").textContent = ""; }, 1000); } });
3. PHP服务器上传配置限制
服务器的PHP配置可能限制了上传文件大小,比如upload_max_filesize、post_max_size设置过小,导致第二次上传(可能文件更大)失败。
- 检查配置:创建
phpinfo.php查看以下参数,确保值大于5MB(建议设为10MB):upload_max_filesizepost_max_sizemax_execution_time
4. 捕获完整的上传错误日志
在PHP中增加错误码处理,明确失败原因:
if (isset($_FILES[$fileInputName])) { switch ($_FILES[$fileInputName]['error']) { case UPLOAD_ERR_OK: // 原有处理逻辑 break; case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_FORM_SIZE: echo "Bestand $i is te groot (overschrijft serverlimiet).<br>"; break; case UPLOAD_ERR_PARTIAL: echo "Bestand $i werd alleen gedeeltelijk geüpload.<br>"; break; case UPLOAD_ERR_NO_FILE: // 无文件上传,跳过 break; default: echo "Onbekende fout bij upload van bestand $i (foutcode: " . $_FILES[$fileInputName]['error'] . ")<br>"; } }
内容的提问来源于stack exchange,提问作者Timotheus
相关产品推荐
相关产品推荐

