使用 XMLHttpRequest 与 FormData 实现无刷新表单及文件上传

键盘旁的猫
键盘旁的猫
发布时间:2026-10-13| 6人浏览过
原创

在 Web 开发中,传统的表单提交会导致页面跳转或刷新。通过组合使用 FormData 对象与 XMLHttpRequest API,开发者可以在不刷新页面的情况下,高效地收集并传输表单数据,包括普通的文本输入和文件上传。本文将提供基于原生 JavaScript 的完整解决方案,涵盖前端数据组装、进度监控以及后端的 PHP 处理逻辑。

核心原理

FormData 是 HTML5 提供的接口,用于模拟表单行为。通过实例化 new FormData(formElement),它可以自动抓取指定表单内所有具有 name 属性的输入域(包括 <input type="file">)及其值。随后,将该对象直接传递给 XMLHttpRequest.send() 方法,即可触发非阻塞的网络请求。

前端实现步骤

第1步:构建 HTML 表单结构

首先创建一个包含文本字段和文件字段的表单。为了演示无刷新效果,表单的 action 应留空或指向自身,关键在于拦截默认的提交行为。同时,添加一个简单的 CSS 容器用于显示上传进度。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <script type="text/javascript">
        window.onload = function(){
            var fm = document.getElementsByTagName('form')[0];
            fm.onsubmit = function(){
                // 1. 实例化 FormData 对象,自动收集表单数据
                var fd = new FormData(fm);
                
                // 2. 创建 XMLHttpRequest 对象
                var xhr = new XMLHttpRequest();
                
                // 3. 监听加载完成状态
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        alert(xhr.responseText);
                    }
                };
                
                // 4. 监听上传进度,更新 UI
                xhr.upload.onprogress = function(evt){
                    if (evt.lengthComputable) {
                        var loaded = evt.loaded;
                        var total = evt.total;
                        // 计算百分比并格式化
                        var per = Math.floor((loaded / total) * 100) + "%";
                        document.getElementById('son').innerHTML = per;
                        document.getElementById('son').style.width = per;
                    }
                };
                
                // 5. 打开连接并发送数据
                // 注意:必须设置为 POST 方法才能传输文件
                xhr.open('POST', './05.php', true);
                xhr.send(fd);
                
                // 阻止表单默认提交行为
                return false;
            }
        }
    </script>
    <style type="text/css">
        #pat {width:430px;height:40px; border:5px solid blue; position:relative; overflow:hidden;}
        #son {width:0;height:100%; background-color:lightblue; transition: width 0.2s;}
    </style>
</head>
<body>
    <h2>Ajax+FormData 实现无刷新文件上传</h2>
    <form method="post" action="" enctype="multipart/form-data">
        <p>用户名:<input type="text" name="username" /></p>
        <p>密码:<input type="password" name="password" /></p>
        <p>邮箱:<input type="text" name="email" /></p>
        
        <!-- 进度条容器 -->
        <div id="pat"><div id="son"></div></div>
        
        <p>头像:<input type="file" name="user_pic" /></p>
        <p><input type="submit" value="注册" /></p>
    </form>
</body>
</html>

关键点说明:

  • 必须在 <form> 标签上设置 enctype="multipart/form-data",这是传输文件的基础要求,虽然 FormData 会自动处理,但保持语义正确很重要。
  • xhr.open() 的第三个参数设为 true 表示异步请求。
  • return false; 是防止浏览器执行标准表单提交导致页面刷新的关键。

第2步:编写 PHP 后端处理逻辑

服务器端需要使用 PHP 接收 $_FILES 数组中的信息。在处理过程中,需注意文件名的字符集转换问题。如果本地环境文件名为 GBK/GB2312 编码,而 PHP 脚本运行在 UTF-8 环境下,直接使用原文件名可能导致乱码或保存失败。

<?php
// 检查上传错误
$error_code = $_FILES['user_pic']['error'];
if ($error_code > 0) {
    exit('上传附件有问题,有可能没有附件');
}

// 获取原始文件名
$name = $_FILES['user_pic']['name'];

// 字符集转换:将 UTF-8 编码的字符串转换为 GB2312
// 这通常用于解决某些旧版 Windows 服务器或特定环境下的文件名乱码问题
$name = iconv('UTF-8', 'GB2312', $name);

// 定义上传目录
$path = "./upload/";

// 确保目录存在且可写(实际项目中建议加入此检查)
if (!is_dir($path)) {
    mkdir($path, 0777, true);
}

// 移动临时文件到最终存储位置
if (move_uploaded_file($_FILES['user_pic']['tmp_name'], $path . $name)) {
    echo "success";
} else {
    echo "fail";
}
?>

注意事项:

  • $_FILES['user_pic']['error'] 为 0 表示上传成功。其他值代表不同级别的错误(如大小超限、部分上传等)。
  • iconv 函数的使用取决于服务器文件系统的实际编码习惯。在现代 UTF-8 普遍支持的 Linux 环境中,可能不需要强制转换,需根据实际部署环境调整。

备选方案:jQuery 方式

如果使用 jQuery 库,可以利用 serializeArray() 或 FormData 简化操作。以下是一个将表单序列化为 JSON 对象并通过 AJAX 提交的辅助函数示例。这种方式更适合仅提交文本数据,不支持文件上传。

// 将 form 中的值转换为键值对对象
function getFormJson(frm) {
    var o = {};
    var a = $(frm).serializeArray();
    $.each(a, function() {
        // 处理同名多个值的情况
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
}

// 执行 AJAX 提交
function ajaxSubmit(url, frm, fn) {
    var dataPara = getFormJson(frm);
    $.ajax({
        url: url,
        type: "post",
        data: dataPara,
        async: false, // 同步提交,视业务需求而定
        dataType: 'txt',
        success: fn
    });
}

总结

通过原生 JS 的 FormData 和 XMLHttpRequest,我们可以精确控制网络请求的细节,包括实时监控上传进度,从而实现体验流畅的无刷新表单交互。对于简单的纯文本表单,jQuery 的序列化方法也是高效的替代方案;但涉及文件传输时,原生 FormData 依然是最标准和通用的选择。

以上就是利用 Ajax+FormData+javascript 实现无刷新表单信息提交的详细内容,更多关于 Ajax FormData 文件上传的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。