目录
4.1.1get传参的两种方式:queryString和/get/id
5.5onload实现onreadystatechange功能
6.3返还数据为json时,xhr.responseXML来获取
1.重点掌握及知识要点
## 重点掌握
- 理解ajax基本使用
- 会使用XMLHttpRequest对象实现数据交互
- 了解onreadystatechange服务器响应信息(状态码)
- 会使用FormData对象上传文件
- 了解upload事件对象(XMLHttpRequest下的事件对象)
## 知识要点
- ajax使用
- XMLHttpRequest对象
- FormData对象
- upload 事件对象
2.登录简单回顾
- 提出ajax验证用户名需求;
- 验证错误后,如果通过跳转解决很麻烦;
- 各种跳转用户体验差
3.利用ajax来解决验证用户名问题
ajax是: Ajax即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML)
3.1ajax的基本使用
- 新建XMLHttpRequest对象;
let xhr = new XMLHttpRequest();
- 配置请求参数
xhr.open("get","/checkUser",true); //true是异步,false是同步
- 接收返还值
xhr.onload = function(){
let res = JSON.parse(xhr.responseText);
}
- 发送服务器请求
xhr.send();
3.2案例实现通过ajax异步无刷新验证用户名
注意:
- 通过 XMLHttpRequest对象中open()方法发起请求。xhr.open("get","/checkUser?username="+this.value,true); //true表示异步发送请求,false同步发送请求,默认为false,所以必须设置为true。
- 通过 XMLHttpRequest对象中onload()方法获取返还数据。注意返回数据是从XMLHttpRequest对象中获得的,xhr.responseText(获取json数据)和xhr.response(获取原始数据),xhr.responseXML(获取XML数据)都可以获取返还数据
- 获取到的数据是JSON格式的,需要将其转为对象。JSON.parse(xhr.responseText).msg
- 后台接收queryString参数通过cxt.query接收;如果是post普通数据传参只需引入koa-body模块,后台通过ctx.request.body接收;如果是post传参且上传文件需引入koa-bodyparser ,然后通过ctx.request.body接收
login.css:
.loginContainer{
margin: 0 auto;
width: 600px;
text-align: center;
padding-top: 20px;
padding-bottom: 50px;
border: 1px solid;
}
.loginContainer input{
margin-bottom: 20px;
}
.loginStyle{
width: 160px;
height: 40px;
background: rgb(50,203,77);
color: white;
font-size: 17px;
}
.inputStyle{
width: 200px;
height: 30px;
padding: 5px;
outline: none;
}
.inputStyle:focus{
border: 1px solid rgb(50,203,77);
}
form{
position: relative;
}
.exchange{
position: absolute;
top:8px;
right: 65px;
color: red;
display: none;
}
user.json:
[
{
"id":1,
"username":"zhangsan",
"pwd":"123"
},{
"id":2,
"username":"lisi",
"pwd":"123"
}
]
login.js:
const Koa = require("koa");
const Router = require("koa-router");
const static = require("koa-static");
// const views = require("koa-views");
const userData = require("./data/user.json");
let app = new Koa();
let router = new Router();
app.use(static(__dirname + "/static"));
//前面页面直接放到static里时,只能通过login.html访问,不能通过/直接访问
router.get("/checkUser", (ctx, next) => {
// 注意接收queryString参数通过cxt.query获得;如果是post传参需引入koa-bodyparser ,然后通过ctx.request.body接收
let username = userData.find(item=>item.username === ctx.query.username);
console.log(ctx.query);
if(username){
// node.js会自动将对象转为json传给前端,所以不用再进行转换
ctx.body = {
status:1,
msg:"用户名正确"
};
}else{
ctx.body = {
status:0,
msg:"用户名错误"
};
}
});
app.use(router.routes());
app.listen("9090");
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="css/login.css" />
<title>Document</title>
</head>
<body>
<div class="loginContainer">
<h1>登录</h1>
<form action="/checkUser" method="post">姓名:
<input class="inputStyle" type="text" name="username" />
<div class="exchange">用户名错误</div>
<br />密码:
<input class="inputStyle" type="password" name="pwd" /><br />
<input class="loginStyle" type="submit" value="登录" />
</form>
</div>
<script>
{
//鼠标失去焦点时,进行无刷新验证
let username = document.querySelectorAll("input");
let exchange = document.querySelector(".exchange");
//使用焦点时验证用户名和密码
username[0].onblur = function(){
let xhr = new XMLHttpRequest();
xhr.open("get","/checkUser?username="+this.value,true);//true表示异步发送请求,false同步发送请求
xhr.onload = function() {
//注意返回数据是从XMLHttpRequest对象中获得的,xhr.responseText和xhr.response都可以获取返还数据
let res = JSON.parse(xhr.responseText);
console.log(JSON.parse(xhr.responseText).msg);
console.log(xhr.response);
exchange.style.display = "block";
//获取到的数据是JSON格式的,需要将其转为对象
exchange.innerHTML = JSON.parse(xhr.responseText).msg;
console.log(res.status);
if(res.status === 1){
exchange.style.color = "green";
}else{
exchange.style.color = "red";
}
}
// 必须调用send()方法
xhr.send();
}
}
</script>
</body>
通过http://localhost:9090/login.html即可请求道login.html页面
4.针对ajax的详细解释
很多ajax框架都是基于XMLHttpRequest对象去实现的,但是很多框架也都存在一定问题,如axiso就不能实现文件或图片上传。
4.1get注意点
- get通过parmas传参
- get和querystring的问题,通过url传参
a标签,img标签中的src和script标签中的src都是使用get请求
4.1.1get传参的两种方式:queryString和/get/id
- queryString,通过queryString传参有长度限制,默认为2048
- /get/id
传参方式注意点:
- querystring传参和get/post请求方式是两个概念,不是使用querystring传参就是get请求,post也可以通过querystring进行传参;通过ctx.query获取传递过来的参数。
- 通过querystring方式进行传参时,后台接收地址不受影响;但如果使用/get/id方式传参,后台必须通过/get/:id方式接收参数,并通过ctx.params获得参数值;
4.1.2queryString传参方式
如上例。
注意queryString传参方式,通过ctx.query获取传递过来的参数。
4.1.3/get/id传参方式
传参方式:‘/请求地址/参数’
接收参数:‘/请求地址/:参数’ 接收地址,使用ctx.params获取参数值
<body>
<button>点击发送get请求</button>
<script>
{
//通过/get/3的方式进行传参,后台通过/get/:id进行获取,ctx.params得到具体参数值
document.querySelector("button").onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("get","/getInfo/1");
xhr.onload = function(){
console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
}
xhr.send();
};
}
</script>
</body>
login.js:get请求(/get/id传参方式)
//get请求(/get/id传参方式)
router.get("getInfo","/getInfo/:id",ctx=>{
console.log(ctx.params);//{ id: '1' }
ctx.body = {
status:1,
msg:"请求成功"
};
});
4.2post传参方式
post传参方式,如果需要发送数据,需要通过send(data)方法进行发送,发送给的数据是通过http正文头发送。
且post传参方式,node.js后台需要使用koa-body进行接收,ctx.request.body获取参数。
注意:如果post请求方式通过queryString方式传参,就需要通过ctx.query获取参数。
4.2.1post传参方式注意点
- post一般不通过queryString进行传参,因为queryString传参有长度限制(服务器会限制),默认2048。
- 发送数据时候需要设置http正文头格式:post传参是通过HTTP正文进行传参,正文传参必须设置编码格式。同form表单的默认编码格式 <form action="" enctype="application/x-www-form-urlencoded"></form>。form表单中可以省略,但是ajax请求时不能省略。
- 需要手动设置正文头,setRequestHeader()的content-type为json且发送的数据通过JSON.stringtify()进行处理,传递过去的数据node才会以对象进行接收。如果没有设置也可以接收,但是需要通过queryString模块ctx.query进行处理,但是前端这样传递数据不好。
注意点:
- 发送数据时候需要设置http正文头格式;
- 获取头部信息:getAllResponseHeaders 或者是getResponseHeader ;
4.2.2post传参方式设置http正文头格式
发送数据时候需要设置http正文头格式:
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); //默认编码
xhr.setRequestHeader("Content-type","multipart/form-data"); //二进制编码,上传文件时使用
xhr.setRequestHeader("Content-type","application/json"); //json编码:传输数据也需要时JSON格式
示例:注意使用post请求时,后台必须使用koa-body模块,才能获取到参数
http正文头格式为默认编码时:
<body>
<button>点击发送post请求</button>
<script>
{
//通过/get/3的方式进行传参,后台通过/get/:id进行获取,ctx.params得到具体参数值
document.querySelector("button").onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("post","/getPostInfo");
xhr.onload = function(){
console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
}
//设置正文请求头
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
let data = "username=zs&age=20";
xhr.send(data);
};
}
</script>
</body>
http正文头格式设置为JSON时:如果正文头是JSON格式,则传输数据也需要是json格式,必须使用JSON.stringify()将数据转为json格式
//正文请求头设置为json时,传输数据也需要是JSON格式
xhr.setRequestHeader("content-type","application/json; charset=utf-8");
let data = JSON.stringify({
username:'zs',
age:12
});
后台获取post参数:需要引入koa-body,然后通过ctx.request.body接收参数
注意:ctx.body是ctx.response.body的别名,而ctx.request.body是post的传参。
const koaBody = require("koa-body");
app.use(koaBody());
//post请求
router.post("/getPostInfo",ctx=>{
console.log(ctx.request.body);//{ username: 'zs', age: '20' }
ctx.body = {
status:1,
msg:"请求成功"
};
});
4.2.3onload()方法中获取返还头部信息
getAllResponseHeaders()获取所有头部信息(某些属性有可能会获取不到,大部分都能获取) 或者是getResponseHeader("请求头属性") 获取某个头部信息
xhr.onload = function(){
console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
//获取所有头部信息
console.log(xhr.getAllResponseHeaders());
//获取某个头部信息
console.log(xhr.getResponseHeader("content-type"));//application/json; charset=utf-8
}
4.2.4完整案例
ajax_post.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button>点击发送post请求</button>
<script>
{
//通过/get/3的方式进行传参,后台通过/get/:id进行获取,ctx.params得到具体参数值
document.querySelector("button").onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("post","/getPostInfo");
xhr.onload = function(){
console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
//获取所有头部信息
console.log(xhr.getAllResponseHeaders());
//获取某个头部信息
console.log(xhr.getResponseHeader("content-type"));
}
//设置正文请求头
// xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");//默认编码
// xhr.setRequestHeader("content-type","multipart/form-data");//二进制编码,上传文件时使用
// let data = "username=zs&age=20";
//正文请求头设置为json时,传输数据也需要是JSON格式
xhr.setRequestHeader("content-type","application/json; charset=utf-8");//json编码:传输数据也需要时JSON格式
// 传输数据也需要是json格式,必须使用JSON.stringify()将数据转为json格式
let data = JSON.stringify({
username:'zs',
age:12
});
xhr.send(data);
};
}
</script>
</body>
</html>
login.js:
app.use(koaBody());
//post请求
router.post("/getPostInfo",ctx=>{
console.log(ctx.request.body);//{ username: 'zs', age: '20' }
ctx.body = {
status:1,
msg:"请求成功"
};
});
结果:所有头部信息
date: Wed, 18 Sep 2019 01:59:50 GMT
connection: keep-alive
content-length: 33
content-type: application/json; charset=utf-8
4.3同步及异步ajax
- 设置异步的请求不会影响其他请求或代码的执行;
- 当设置同步执行时,其后其他请求或代码必须等该请求执行完后,才会进行执行
异步:设置异步的请求不会影响其他请求或代码的执行
<body>
<button>按钮一</button>
<button>按钮二</button>
<script>
{
let btns = document.querySelectorAll("button");
btns[0].onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("get","/getInfo/2",true);
xhr.onload = function(){
console.log(xhr.responseText);
}
xhr.send();
}
//点击第二个按钮时进行打印
btns[1].onclick = function(){
console.log("按钮二打印。。。");
}
}
</script>
</body>
结果:按钮一的请求不会影响按钮二的打印结果(测试时网速太快看不到效果,可以将Network中的online网络改为slow3G再测)
异步:当设置同步执行时,其他请求或代码必须等该请求执行完后,才会进行执行
xhr.open("get","/getInfo/2",false);
结果:永远都只会先打印按钮一发送的请求后再执行按钮二的请求
4.4onload()
以前是使用onreadystatechange后,通过readyState的状态判断是否请求完毕,现在使用onload()更加简洁方便。
onload()方法是异步的,即使写在send()方法前面也会再send()方法执行后才会执行,一般习惯上会将send()方法放在最后面。因为很多东西必须在send()之前设置才有用,如setRequestHeader()就必须在send()之前设置。
5.onreadystatechange——了解
5.1onreadystatechange
onreadystatechange:存有处理服务器响应的函数,每当 readyState 改变时,onreadystatechange 函数就会被执行。
5.2readyState
readyState:存有服务器响应的状态信息。
- 0: 请求未初始化(代理被创建,但尚未调用 open() 方法)
- 1: 服务器连接已建立(`open`方法已经被调用)
- 2: 请求已接收(`send`方法已经被调用,并且头部和状态已经可获得)
- 3: 请求处理中(下载中,`responseText` 属性已经包含部分数据)
- 4: 请求已完成,且响应已就绪(下载操作已完成)
5.3status常用状态码
HTTP状态码 | 描述 |
---|---|
100 | 继续。继续响应剩余部分,进行提交请求 |
200 | 成功 |
301 | 永久移动。请求资源永久移动到新位置 |
302 | 临时移动。请求资源零时移动到新位置 |
304 | 未修改。请求资源对比上次未被修改,响应中不包含资源内容 |
401 | 未授权,需要身份验证 |
403 | 禁止。请求被拒绝 |
404 | 未找到,服务器未找到需要资源 |
500 | 服务器内部错误。服务器遇到错误,无法完成请求 |
503 | 服务器不可用。临时服务过载,无法处理请求 |
5.4onreadystatechange示例:
<body>
<button>点击</button>
<script>
document.querySelector("button").onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("get","/getInfo/3",true);
xhr.onreadystatechange = function(){
//判断服务求响应状态为4和返还状态200(成功)
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
}
}
}
xhr.send();
};
</script>
</body>
5.5onload实现onreadystatechange功能
其实,使用onload也有服务器响应信息和返回状态码:建议使用onload会更加简洁
xhr.onload = function(){
console.log(xhr.readyState);//4
console.log(xhr.status);//200
console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
}
6.返还数据类型(XML,JSON)
前端和后台之前,平台和平台之间数据传输都会使用同一的数据格式,现在主流的数据跨平台交互有XML和JSON。
6.1获取原始数据xhr.response
//获取原始数据
console.log(xhr.response);
6.2返还数据为json时xhr.responseText
- 服务器返还json数据:xhr.responseText 来获取
xhr.responseText //来获取
6.3返还数据为json时,xhr.responseXML来获取
- 服务器返还xml数据 :
- xhr.responseXML //获取值
- 服务器端设置response里的content-type内容ctx.set("content-type","text/xml");
- 前端重写XML(以防后台没有指定content-type类型):xhr.overrideMimeType('text/xml;charset=utf-8');注意属性之间不能有空格
- 前端和服务器端随便那边设置返还数据格式即可,不需要都设置
xhr.responseXML //获取值
示例:
前端HTML:
<body>
<button>点击获取XML数据</button>
<script>
{
document.querySelector("button").onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("get","/getXMLInfo",true);
//如果后台没有设置XML的content-type,前端就必须重写格式
xhr.overrideMimeType('text/xml;charset=utf-8');
xhr.onload = function(){
//获取XML格式数据
console.log(xhr.responseXML);
console.log(xhr.responseXML.getElementsByTagName("name")[0]);
//获取原始数据
console.log(xhr.response);
}
xhr.send();
}
}
</script>
</body>
后台:
//获取XML数据
router.get("/getXMLInfo",ctx=>{
ctx.set("content-type","text/xml");
//注意这里反引号和xml内容不能换行
ctx.body = `<?xml version='1.0' encoding='utf-8' ?>
<books>
<nodejs>
<name>nodeJS实战</name>
<price>52.0元</price>
</nodejs>
<react>
<name>react进阶</name>
<price>56.0元</price>
</react>
</books>`;
});
结果:
为防止后台没有写XML的content-type,需要在前端重写XML格式:
xhr.overrideMimeType('text/xml;charset=utf-8');
7.利用FormData对象来实现文件上传
7.1 创建FormData对象
注意点:
- <input type="file" class="myfile">通过files属性获取到的是类数组;
- 通过new FormData()创建文件上传对象;
- formData.append(name,value);name必须和后台接收时name保持一致,value可以是文件也可以是普通数据
- 文件上传必须通过正文方式进行传递,所以必须使用post请求;
- 使用FormData时会自动对content-type进行设置,就不需要再进行手动设置
- 后台接收数据时,通过前端append()中的name属性即可获取到对应数据或文件
- 再通过fs模块对相应文件进行转存即可。ctx.request.files.img.path即文件的临时路径,对临时路径中的文件转存到服务器下路径即可
- 文件转存时有可能出现文件夹权限问题,需要手动开启权限。且文件夹不存在,需要先创建文件夹
示例:
前端:注意上传文件是通过正文提交,所以必须使用post方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="file" class="myfile">
<button>点击上传</button>
<script>
document.querySelector("button").onclick = function(){
let myfile = document.querySelector(".myfile");
//files属性返回的是类数组
let files = myfile.files;
//创建FormData对象,进行上传(使用FormData后,就不需要在表单中使用form-data进行上传)
let formData = new FormData();
//img表示name,相当于form表单中的name属性,file[0]表示要上传的单个文件
formData.append("img",files[0]);
//其他的数据,也可以进行传输
formData.append("username","张三");
//文件上传必须通过正文方式进行传递,所以必须使用post请求
//使用FormData时会自动对content-type进行设置,就不需要再进行手动设置
let xhr = new XMLHttpRequest();
xhr.open("post","/upload",true);
xhr.onload = function(){
console.log(xhr.responseText);
};
// 没选择文件需要提示,否则会报错
if(files>0){
xhr.send(formData);
}else{
alert("请选择文件");
}
};
</script>
</body>
</html>
后台:获取上传文件必须使用mutipart:ture;通过ctx.request.files.img获取文件
const Koa = require("koa");
const Router = require("koa-router");
const static = require("koa-static");
const koaBody = require("koa-body");
const fs = require("fs");
let app = new Koa();
let router = new Router();
app.use(static(__dirname + "/static"));
//上传文件时,必须设置允许文件上传,否则接收不了
app.use(koaBody({
multipart:true
}));
//上传文件
router.post("/upload",ctx=>{
//通过前端append()中的name属性即可获取到对应数据或文件
// console.log(ctx.request.body);//{ username: '张三' }
// console.log(ctx.request.files.img);
//通过fs模块对相应文件进行转存即可
//ctx.request.files.img.path即文件的临时路径,对临时路径中的文件转存到服务器下路径即可
let fileData = fs.readFileSync(ctx.request.files.img.path);
//文件转存时有可能出现文件夹权限问题,需要手动开启权限
//判断文件夹不存在,需要先创建文件夹
if(!fs.existsSync("static/imgs")){
fs.mkdirSync("static/imgs/");
}
fs.writeFileSync("static/imgs/"+ctx.request.files.img.name,fileData);
ctx.body = {
status:1,
msg:"文件上传成功"
};
});
app.use(router.routes());
app.listen("8888");
结果:{"status":1,"msg":"文件上传成功"}
7.2 监控上传进度——upload 事件
7.2.1upload事件下的各种事件——事件钩子
以下事件都是在upload事件下:
- onloadstart 上传开始
- onprogress 数据传输进行中(evt.total :需要传输的总大小;evt.loaded :当前上传的文件大小;)
- onabort 上传操作终止(取消上传xhr.abort())
- onerror 上传失败
- onload 上传成功
- onloadend 上传完成(不论成功与否)
7.2.2监控文件上传进度示例
注意点:
- 使用<process>标签可以显示文件上传进度
- 监控文件上传速度(需要onloadstart和onprogress的时间差,及时间差内文件已上传的文件大小),当前文件大小/时间差 即文件上传速度;时间差需要转为单位为秒
- evt.total :需要传输的总大小;evt.loaded :当前上传的文件大小
- 需要处理上传的单位b/s ,判断文件足够大时使用kb/s;
文件上传页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.progressSpan{
display: none;
color: seagreen;
}
</style>
</head>
<body>
<input type="file" class="myfile">
进度:<progress value="0" max="100"></progress> <span class="progressSpan">10%</span>
速度:<span class="speed">20b/s</span><br><br>
<button>点击上传</button>
<button>取消上传</button>
<script>
{
let btns = document.querySelectorAll("button");
let xhr = new XMLHttpRequest();
btns[0].onclick = function(){
let sTime = 0;//文件开始上传时间
let eTime = 0;//文件开始上传时间
let fileInitSize = 0;//文件开始上传大小
xhr.open("post","/fileUpload",true);
//获取上传文件
let file = document.querySelector(".myfile").files[0];
let formData = new FormData();
formData.append("imgFile",file);
//upload事件监控文件上传进度
xhr.upload.onloadstart = function(){
console.log("文件开始上传");
sTime = new Date().getTime();
fileInitSize = 0;
};
xhr.upload.onprogress = function(evt){
console.log("文件上传中");
//在onprogress事件中监控上传进度
let progress = (evt.loaded / evt.total * 100).toFixed(0);
//将进度进行显示
document.querySelector("progress").value = progress;
document.querySelector(".progressSpan").style.display = "inline-block";
document.querySelector(".progressSpan").innerHTML = progress+"%";
//监控文件上传速度(需要onloadstart和onprogress的时间差,及时间差内文件已上传的文件大小)
eTime = new Date().getTime();
//需要将时间差转为秒s
let diffTime = (eTime-sTime)/1000;
//各个进度文件上传的文件大小
let curFileSize = evt.loaded;
let diffFileSize = curFileSize - fileInitSize;
//获取上传速度(需要处理上传的单位b/s kb/s)
let speed = diffFileSize/diffTime;
let unit = "";
if(speed/1024>1){
speed = speed/1024;
unit = "b/s";
}
if(speed/1024>1){
speed = speed/1024;
unit = "kb/s";
}
document.querySelector(".speed").innerHTML = speed.toFixed(2)+unit;
//使用当前文件大小/时间差 即文件上传速度
sTime = eTime;
fileInitSize = curFileSize
};
xhr.upload.onabort = function(){
console.log("取消文件上传");
};
xhr.upload.onerror = function(){
console.log("文件上传失败");
};
//上传成功
xhr.upload.onload = function(){
console.log(xhr.responseText);
};
xhr.upload.onloadend = function(){
console.log("文件上传完成");
};
xhr.send(formData);
};
btns[1].onclick = function(){
//取消文件上传方法
xhr.abort();
};
}
</script>
</body>
</html>
后台处理:
//监控文件上传进度
router.post("/fileUpload",(ctx,next)=>{
//通过前端append()中的name属性即可获取到对应数据或文件
//ctx.request.files.imgFile.path即文件的临时路径,对临时路径中的文件转存到服务器下路径即可
let fileData = fs.readFileSync(ctx.request.files.imgFile.path);
//判断文件夹不存在,需要先创建文件夹
if(!fs.existsSync("static/imgs")){
fs.mkdirSync("static/imgs/");
}
fs.writeFileSync("static/imgs/"+ctx.request.files.imgFile.name,fileData);
ctx.body = {
status:1,
msg:"文件上传成功"
};
});
结果:
8.回顾
1.ajax基本使用:创建XMLHttpRequest对象,xhr.open(),xhr.onload,xhr.send()
2.get/post在ajax中的使用
3.ajax中成功的返还:onload
4.返还数据格式:response,responseText,responseXML
5.FormData对象:创建FormData对象,form.append(name,value)
6.upload事件对象:各个监控文件上传的事件方法