上文讨论了ajax请求体3种常用类型和场景,以及前两种类型(查询字符串,json对象)的上传方法,这篇文章将浅谈一下请求体第三种数据类型(文件对象)的上传方法
请求头Content-Type类型 请求体值格式
1. application/x-www-form-urlencoded 参数名=值&参数名=值 的字符串
2. application/json '{"参数名": 值, "参数名": 值} 的json字符串
3. multipart/form-data FormData表单数据(常用携带文件)
第三种数据类型(文件对象)的上传方法使用FormData语法
1.实例化一个对象 const fd = new FormData
2.用它的append方法加入参数名和值
<script>
const fd = new FormData()
fd.append('name','xiaoma');
fd.append('age',18)
fd.append('word','abc')
fd.forEach((value,key)=>{
console.log(value,key);
})
console.log(fd);
</script>
我们可以看到,直接打印实例化对象fd是无法直接观察里面的对象的(请看打印台第18行)
必须要用forEach的方法遍历这个实例化对象才能打印出里面的值.而且需要注意的是这里的fd不能看成一个普通的数组或对象,所以不能直接打印 fd 这个实力化对象来观察他里面的内容
下面举一个FormData语法的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例_头像上传</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<style>
.thumb-box {
text-align: center;
margin-top: 50px;
}
.thumb {
width: 250px;
height: 250px;
object-fit: cover;
border-radius: 50%;
border: 5px solid black !important;
}
</style>
</head>
<body>
<div class="thumb-box">
<!-- 头像 -->
<img id="img" class="img-thumbnail thumb" src="../image/10.23.png">
<div class="mt-2">
<!-- 文件选择框(因为无法改样式, 所以css隐藏, 但是还可以用js获取) -->
<input type="file" id="iptFile"
accept="image/*">
<button id="btn">选择你的头像</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.27.2/dist/axios.min.js"></script>
<script>
document.querySelector('#iptFile').addEventListener('change',(e)=>{
console.log(e.target.files);
if(e.target.files.length===0){
return
}
const file = e.target.files[0]
const fd = new FormData()
fd.append('avatar',e.target.files[0])
axios({
url:'http://ajax-api.itheima.net/api/file',
method:'POST',
data:fd
}
).then(res=>{
console.log( res.data.data.url);
document.querySelector('#img').src = res.data.data.url
})
})
</script>
</body>
</html>
案例是一个上传用户头像
这里我们使用了FormData语法,存放了文件对象的数据,并且把这个文件对象数据上传
刚开始,我用一般的思路:既然这是一个文件对象,那么我只用把文件对象地址通过ajax直接上传不就行了吗? 我们来看下不用FormData语法存放文件对象的效果
<script>
document.querySelector('#iptFile').addEventListener('change',(e)=>{
console.log(e.target.files);
if(e.target.files.length===0){
return
}
const file = e.target.files[0]
// const fd = new FormData()
// fd.append('avatar',e.target.files[0])
axios({
url:'http://ajax-api.itheima.net/api/file',
method:'POST',
data:{
'avatar':e.target.files[0]
}
}
).then(res=>{
console.log(res.data.data);
document.querySelector('#img').src = res.data.data.url
})
})
</script>
上面代码段,我把文件对象地址直接写到axios里面的参数里面.可是我们到请求载荷里面发现,上传的参数只是一个avatar的空对象,这个对象里面的值无法被提取,
此时就要用到FormData语法,封装这个文件对象的数据,它的作用就是让ajax能够完整提取文件对象里面的数据
如果封装完成,数据上传后全部读取,就会是下面的效果
总结,ajax中请求体文件对象的上传,必须使用FormData语法,不然就会造成数据无法正常读取,只能读取到一段空的对象