利用FormData对象 + XHR 新特性实现文件上传——带进度条
Posted 啵啵丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用FormData对象 + XHR 新特性实现文件上传——带进度条相关的知识,希望对你有一定的参考价值。
小编今天又get到一个新技能,就是上传图片并显示进度条,话不多说,直接进入正题!冲冲冲!!💪
实现效果:
当点击上传文件按钮后,如果未选择文件,会跳出请选择要上传的文件提示框,反之,会有一个上传图片的进度条显示,当上传完成后,图片也会对应的显示在页面中.
实现步骤:
① 定义UI 结构
② 验证是否选择了文件
③ 向 FormData 中追加文件
④ 使用 xhr 发起上传文件的请求
⑤ 监听 onreadystatechange请求
⑥ 显示文件上传进度
⑦ 基于 bootstrap 绘制进度条效果
⑧ 监听上传完整的事件
【接下来我会根据实现步骤来一一说明,最后会附上完整代码,认真看哟~ 】
分步解析:
① 定义UI 结构
先引入相关的文件,bootstrap.css 和 jQuery.min.js
开始布局页面基本结构(代码如下图所示)
其中进度条的样式是从bootstrap官网——>组件——>进度条中挑选的
最后给一个 Img 标签用来显示上传到服务器的图片
<!-- 文件选择框 -->
<input type="file" id="file1">
<button id="btn">上传文件</button>
<br>
<!-- 引用 bootstrap中的进度条 -->
<div class="progress" style="width: 500px; margin: 15px 10px">
<div class="progress-bar progress-bar-striped active"style="width: 0" id="percent">
0
</div>
</div>
<!--显示上传到服务器的图片-->
<img src="" alt="" id="img" width="800">
② 验证是否选择了文件
先获取到上传文件的按钮并为它添加点击事件
获取到选择的文件列表(files)
其中 var files = document.querySelector('#file1').files
通过id获取文件选择框,在文件选择框中有一个 files 属性,它是一个数组,里面存放用户 选择的文件,判断 它的length是否小于等于0,如果是,则没有选择文件
<script>
// 1.获取上传文件的按钮
var btn = document.querySelector('#btn')
// 2.为按钮添加 click 事件监听
btn.addEventListener('click',function(){
// 3.获取到选择的文件列表
var files = document.querySelector('#file1').files
if(files.length <= 0) {
return alert('请选择要上传的文件!')
}
}
</script>
③ 向 FormData 中追加文件
Ajax 操作往往用来提交表单数据。为了方便表单处理,html5新增一个 formData 对象,可 以模拟表单操作
通过 append 就可以向 FormData 中追加文件
//1. 创建 FormData 对象
var fd = new FormData()
//2. 向 FormData 中追加文件,('自定义文件名',文件),因为是一个数组,取第一个文件所以索引为0
fd.append('avatar',files[0])
④ 使用 xhr 发起上传文件的请求
XMLHttpRequest(简称 xhr) 是浏览器提供的 javascript 对象,通过它,可以 请求服务器上 的数据资源
创建完 xhr 对象后,通过调用 open 函数,指定 请求方式 与 URL地址
这里需要注意!因为是上传文件,所以请求方式必须为 post
调用 send 函数,发起 Ajax 请求
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数,指定请求类型与URL地址。其中,请求类型必须为 post
xhr.open('POST','http://www.liulongbin.top:3006/api/upload/avatar')
// 3. 发起请求
xhr.send(fd)
⑤ 监听 onreadystatechange 请求
监听 xhr 对象的 请求状态 readyState; 与服务器的 响应状态 status
如果 xhr.readyState 全等于 4 且 xhr.status 全等于 200 ,就获取从服务器响应回来的数据,
并把它转换为 JS 对象(方便后续获取里面的值) 存放在 自定义的 data 对象中
获取到的 data 数据中有很多的属性,其中 data.status 代表上传的状态,如果为 200则表示上传成功
如果上传成功就把上传的图片显示在页面中
xhr 对象的 readyState 属性
值 状态 描述 0 UNSENT XMLHttpRequest 对象已被创建,但尚未调用 open() 方法 1 OPENED open() 方法已经被调用 2 HEADERS_RECEIVED send() 方法已经被调用,响应头也已经被接收 3 LOADING 数据接收中,此时 response 属性中已经包含部分数据 4 DONE Ajax 请求完成,这意味着数据传输已经彻底完成或失败
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText)
if(data.status === 200) {
// 上传成功
// 将服务器返回的图片地址,设置为 <img> 标签的 src 属性
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
// 上传失败
console.log('图片上传失败!' + data.message);
}
}
}
⑥ 显示文件上传进度
新版本的 XHLHttpRequest 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取 到文件的上传进度
//做文件上传的进度
xhr.upload.onprogress = function(e) {
//e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
if(e.lengthComputable) {
// e.loaded 已传输的字节
// e.total 需传输的总字节
var percentComplete = Math.ceil((e.loaded/e.total) * 100)
}
}
⑦ 基于 bootstraps 绘制进度条效果
把算出的上传进度的百分比赋值给从 bootstrap 中引入的模板中,从而实现将进度绘制到页面
//将进度渲染到页面
$('#percent').attr('style','width:' + percentComplete + '%;').html(percentComplete + '%')
⑧ 监听上传完整的事件
通过监听 xhr.upload.onload 事件来表示文件是否上传完整,上传完整后,将进度条修改为绿色
xhr.upload.onload = function() {
// 移除当前样式,添加 新样式
$('#percent').removeClass().addClass('progress-bar progress-bar-success')
}
完整代码
<!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>Document</title>
<link rel="stylesheet" href="../bootstrap.css">
<script src="../jQuery.min.js"></script>
</head>
<body>
<input type="file" id="file1">
<button id="btn">上传文件</button>
<br>
<!-- bootstrap中的进度条 -->
<div class="progress" style="width: 500px; margin: 15px 10px">
<div class="progress-bar progress-bar-striped active"style="width: 0" id="percent">
0
</div>
</div>
<img src="" alt="" id="img" width="800">
<script>
// 1.获取上传文件的按钮
var btn = document.querySelector('#btn')
// 2.为按钮添加 click 事件监听
btn.addEventListener('click',function(){
// 3.获取到选择的文件列表
var files = document.querySelector('#file1').files
if(files.length <= 0) {
return alert('请选择要上传的文件!')
}
//1. 创建 FormData 对象
var fd = new FormData()
//2. 向 FormData 中追加文件
fd.append('avatar',files[0])
var xhr = new XMLHttpRequest()
//做文件上传的进度
xhr.upload.onprogress = function(e) {
//e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
if(e.lengthComputable) {
// e.loaded 已传输的字节
// e.total 需传输的总字节
var percentComplete = Math.ceil((e.loaded/e.total) * 100)
//将进度渲染到页面
$('#percent').attr('style','width:' + percentComplete + '%;').html(percentComplete + '%')
}
}
xhr.upload.onload = function() {
$('#percent').removeClass().addClass('progress-bar progress-bar-success')
}
xhr.open('POST','http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText)
if(data.status === 200) {
// 上传成功
// 将服务器返回的图片地址,设置为 <img> 标签的 src 属性
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
// 上传失败
console.log('图片上传失败!' + data.message);
}
}
}
})
</script>
</body>
</html>
这次的分享到这就结束啦~大家快去试试把!
以上是关于利用FormData对象 + XHR 新特性实现文件上传——带进度条的主要内容,如果未能解决你的问题,请参考以下文章
如何将 enctype 属性添加到 FormData() 对象?