使用 XMLHttpRequest 与 FormData 实现无刷新表单及文件上传
在 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 文件上传的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









