You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XMLHttpRequest、FormData上传file至PHP失败及回调未触发问题求助

问题分析与解决方案

核心错误原因(无<form>方案)

  1. FormData.append参数错误:你传入的是文件输入框元素本身,而非选中的文件对象。input[type=file]的文件数据存在files属性里,需要取files[0]才能拿到选中的文件。
  2. 重复调用XMLHttpRequest.open():连续两次调用RQ.open("Post", 'comp03.php')会重置请求状态,属于冗余操作。
  3. 变量未声明:FD、t、RQ等变量未用let/const声明,会变成全局变量,可能引发意外冲突。
  4. 状态判断逻辑错误:CheckSt函数里的'Problem XMLHttpResponse = ' + RD.status == 200会把RD.status ==200当作布尔运算,导致输出错误内容。
  5. 非标准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'>&nbsp;</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未触发的核心原因:

  1. document.querySelector('#CompFiles')是按ID选择,但表单使用的是name='CompFiles',需改为document.querySelector('form[name="CompFiles"]')。
  2. FDx=FDt.entries需改为FDx=FDt.entries(),因为entries()是方法,需调用才能获取迭代器。
  3. 循环变量A与判断里的a大小写不一致,导致逻辑失效。
  4. 未阻止表单默认提交行为,需在CompFiles函数末尾添加return false或event.preventDefault()。

不过既然你希望不依赖<form>标签,上述修正方案已满足需求。

内容的提问来源于stack exchange,提问作者Howard Cary Morris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 05:57:01