XMLHttpRequest、FormData上传file至PHP失败及回调未触发问题求助
问题分析与解决方案
核心错误原因(无<form>方案)
- FormData.append参数错误:你传入的是文件输入框元素本身,而非选中的文件对象。
input[type=file]的文件数据存在files属性里,需要取files[0]才能拿到选中的文件。 - 重复调用XMLHttpRequest.open():连续两次调用
RQ.open("Post", 'comp03.php')会重置请求状态,属于冗余操作。 - 变量未声明:
FD、t、RQ等变量未用let/const声明,会变成全局变量,可能引发意外冲突。 - 状态判断逻辑错误:
CheckSt函数里的'Problem XMLHttpResponse = ' + RD.status == 200会把RD.status ==200当作布尔运算,导致输出错误内容。 - 非标准HTML标签:自定义的
<red>、<blue>标签不会被浏览器识别,应该用标准的<span>配合样式实现颜色效果。
修正后的前端代码
JavaScript代码
let OFC; function CompFiles() { OFC = document.getElementById('FC'); OFC.innerHTML = '<i>comparing files at a web site</i>'; // 获取文件输入框 const file1Input = document.getElementsByName('file1')[0]; const file2Input = document.getElementsByName('file2')[0]; // 校验文件是否选中 if (!file1Input.files.length) { OFC.innerHTML = '<span style="color:red">file 1 has not been selected yet</span>'; file1Input.focus(); return; } if (!file2Input.files.length) { OFC.innerHTML = '<span style="color:red">file 2 has not been selected yet</span>'; file2Input.focus(); return; } // 构建FormData,传入文件对象 const FD = new FormData(); FD.append('file1', file1Input.files[0]); FD.append('file2', file2Input.files[0]); // 发送请求 const RQ = new XMLHttpRequest(); RQ.open("POST", 'comp03.php'); RQ.onload = () => { CheckSt(RQ); }; // 处理请求错误 RQ.onerror = () => { OFC.innerHTML = '<span style="color:red">Request failed</span>'; }; RQ.send(FD); } function CheckSt(RD) { const O = OFC; if (RD.status === 200) { O.innerHTML = `<span style="color:blue">${RD.responseText}</span>`; } else { O.innerHTML = `<span style="color:red">Problem XMLHttpResponse status = ${RD.status}</span>`; } }
HTML代码
<p>See if two files are equal. See first line where they differ<br> First file: <input type='file' name='file1'> Second file: <input type='file' name='file2'> <button onclick='CompFiles()'>compare the two files</button><br> <span id='FC'> </span></p>
PHP后端处理代码(comp03.php)
<?php // 校验文件是否上传成功 if (!isset($_FILES['file1']) || !isset($_FILES['file2']) || $_FILES['file1']['error'] !== UPLOAD_ERR_OK || $_FILES['file2']['error'] !== UPLOAD_ERR_OK) { echo "Error: Failed to upload files"; exit; } // 打开两个文件 $file1 = fopen($_FILES['file1']['tmp_name'], 'r'); $file2 = fopen($_FILES['file2']['tmp_name'], 'r'); if (!$file1 || !$file2) { echo "Error: Failed to read files"; exit; } $lineNum = 1; $areEqual = true; // 逐行对比(去除换行符避免系统差异) while (($line1 = fgets($file1)) !== false && ($line2 = fgets($file2)) !== false) { if (rtrim($line1, "\r\n") !== rtrim($line2, "\r\n")) { echo "Files differ at line $lineNum:\nFile1: " . htmlspecialchars($line1) . "\nFile2: " . htmlspecialchars($line2); $areEqual = false; break; } $lineNum++; } // 检查是否有文件存在额外内容 if ($areEqual) { $line1 = fgets($file1); $line2 = fgets($file2); if ($line1 !== false) { echo "File1 has extra content starting at line $lineNum:\n" . htmlspecialchars($line1); $areEqual = false; } elseif ($line2 !== false) { echo "File2 has extra content starting at line $lineNum:\n" . htmlspecialchars($line2); $areEqual = false; } } if ($areEqual) { echo "The two files are identical"; } // 关闭文件 fclose($file1); fclose($file2); ?>
关于第二次尝试方案的补充说明
你第二次方案中CheckSt未触发的核心原因:
document.querySelector('#CompFiles')是按ID选择,但表单使用的是name='CompFiles',需改为document.querySelector('form[name="CompFiles"]')。FDx=FDt.entries需改为FDx=FDt.entries(),因为entries()是方法,需调用才能获取迭代器。- 循环变量
A与判断里的a大小写不一致,导致逻辑失效。 - 未阻止表单默认提交行为,需在
CompFiles函数末尾添加return false或event.preventDefault()。
不过既然你希望不依赖<form>标签,上述修正方案已满足需求。
内容的提问来源于stack exchange,提问作者Howard Cary Morris
相关产品推荐
相关产品推荐

