文章目录
Ajax预备知识
post和get区别
get
(1)会将上传的内容写在url后面,安全性不高
(2)有最大上传大小限制
post
(1)上传的内容在包头部,url上看不到
(2)没有最大上传大小限制
应用场景
通常小文件,不考虑安全性的时候用get方法。
大文件和需要保密的时候用post
使用服务器实现简单的文件上传(post方法)
(服务器使用wamp)
- 注意事项
(1)上传文件要用post方法(可能比较大,get限制大小,且更安全)
(2)表单要指定enctype为二进制格式,否则无法读取,只能读到文件名
(3)后端php使用$_FILES[name]获取该文件字典,name为input的name
(4)PHP中会把文件暂时放在一个临时目录,但无法直接从这里取到文件,因为这里的文件不进行处理就会被快速删除,需要把这里的文件拿出来存到自己指定的位置,用到move_uploaded_file方法
(5)路径不要带中文,否则会报错。
- 简单上传
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<form action="upload1.php" method="post">
<input type="file" name="upload" id="upFIle" />
<input type="submit" value="upload" />
</form>
</body>
</html>
php
<?php
print_r($_POST);
?>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4sYSJqg4-1603972484193)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20201023154213483.png)]
- 保存上传的文件
注意 表单要用二进制格式才能读取到上传的文件(enctype)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<form action="upload1.php" method="post" enctype="multipart/form-data">
<input type="file" name="upload" id="upFIle" />
<input type="submit" value="upload" />
</form>
</body>
</html>
<?php
// 1.获取上传文件对应的字典(key-value格式)
$fileInfo=$_FILES['upload'];
// print_r($fileInfo);
// 2.获取文件名
$fileName=$fileInfo['name'];
// 3.获取文件的临时保存路径
$filePath=$fileInfo['tmp_name'];
// 4.保存文件
//第一个参数上传上来的文件的暂时路径
//第二个参数要保存的路径(包括文件名)
move_uploaded_file($filePath,'./source/'.$fileName);
?>
大型文件上传
-
虽然post方法上传理论上没有大小限制,但web服务器对上传的文件大小有限制,需要进行修改
-
修改php.ini
(1)位置:wamp目录–bin–apache–bin
(2)要修改的位置:
1.file_uploads=On 默认应该就是On,不用改
2.upload_max_filesize=2048M 上传文件最大大小
3.post_maxsize=2048M post方法上传最大大小
4.max_execution_time=30000 脚本执行的最长时间 秒
5.max_input_time=3000 接收提交数据的时间限制 秒
6.memory_limit=2048M 内存消耗限制
Ajax基本概念
- 使用ajax,可以在不更新整个网页的前提下进行交互。比如百度搜索框下弹出的可能内容
- ajax是基于JS的前端技术
Ajax-GET方法
GET方法基本使用
- 使用步骤
1.创建xmlhttp异步对象
2.设置请求方式和地址
3.发送请求
4.监听状态,进行处理
- 具体代码
(1)php部分随便写
get1.php
<?php
echo 'hello world ajax !'
?>
(2)在html页面中写JS脚本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>send message</button>
<script>
let btn = document.querySelector("button");
btn.onclick = function (val) {
// 1.创建异步对象
let xmlhttp = new XMLHttpRequest();
// 2.设置请求方式和地址
xmlhttp.open("GET", "./get1.php", true);
/*
open的参数
01 请求方式 GET / POST
02 请求地址
03 同步false/异步true ajax固定异步,必须是true
*/
// 3.发送请求
xmlhttp.send();
// 4.监听状态
xmlhttp.onreadystatechange = function (val2) {
// 5.进行处理
// 5.1当消息传输完成时才进行处理
if (xmlhttp.readyState === 4) {
// 5.2判断消息是否正常传输,没有发生错误
if (
(xmlhttp.status >= 200 && xmlhttp.status < 300) ||
xmlhttp.status === 304
) {
// 5.3对成功状态进行处理
console.log("传输完成!");
} else {
console.log("传输出错!");
}
}
};
};
</script>
</body>
</html>
(3)结果:
传输出错的结果
正确的结果
- 状态码总结
(1)readyState
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
(2)state
[200,300)都是成功
304 是访问了本地缓存,也算成功
404 是未找到页面
- 获得服务器返回的数据
(1)XML格式数据
xmlhttp.responseXML
(2)字符串类型数据
xmlhttp.responseText
修改代码后
再次请求
GET方法 IE兼容问题
- XMLHttpRequest对象的IE兼容
使用下面代码创建xmlhttp ,能够具有IE兼容
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
- IE请求最新数据问题
IE认为同一个URL的内容是固定的,要想实时获得最新数据,必须用不同的url进行请求
解决方案:在url后面加上一段额外字符,没有实际意义,只为了兼容IE
可以使用随机数random也可以使用时间date
xmlhttp.open("GET", "get1_IE.txt?"+(Math.random()), true);
封装Ajax的GET请求
基本封装
- 意义:每次定义的Ajax操作都是大同小异,为了减少工作量应该把其封装成一个函数
- 封装方法
需要改变的地方设置成封装方法的参数:
(1)请求的url
(2)成功后的处理 传入一个回调函数success(xhr)
(3)失败时的处理 传入一个回调函数error(xhr)
function myAjaxGet(url, success, error) {
let btn = document.querySelector("button");
btn.onclick = function (val) {
// 1.创建异步对象
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和地址
xmlhttp.open("GET", url + '?t=' + (new Date().getTime()), true);
/*
open的参数
01 请求方式 GET / POST
02 请求地址
03 同步false/异步true ajax固定异步,必须是true
*/
// 3.发送请求
xmlhttp.send();
// 4.监听状态
xmlhttp.onreadystatechange = function (val2) {
// 5.进行处理
// 5.1当消息传输完成时才进行处理
if (xmlhttp.readyState === 4) {
// 5.2判断消息是否正常传输,没有发生错误
if (
(xmlhttp.status >= 200 && xmlhttp.status < 300) ||
xmlhttp.status === 304
) {
// 5.3对成功状态进行处理
success(xmlhttp);
} else {
error(xmlhttp);
}
}
};
};
}
- 使用该封装方法
1.引入封装方法的JS文件
<script src="./get_wrap.js"></script>
2.调用该函数,并定义两个回调函数
<script>
myAjaxGet('get1_IE.txt',(xhr)=>{
alert(xhr.responseText);
},(xhr)=>{
console.log('error!');
})
</script>
结果
将请求内容放到url上
- 给封装的方法新增一个参数,用来接收要被放在url上的请求内容
- 将请求封装在一个对象内传递到ajax方法中,即新参数是一个对象
变化:
1.新增方法obj2str
2.myAjaxGet方法新增参数obj
3.方法内部处理url的地方改成 url+"?"+(obj处理成的str)
function obj2str(obj) {
/*
obj的格式为 key:val
将它转成字符串 key1=val1&key2=val2 的形式
*/
// 将用于兼容IE的时间随机数也放进来一起处理
obj.t = new Date().getTime();
let ret = [];
// 形成[key1=val1,key2=val2]形式的数组
for (key in obj) {
ret.push(key + '=' + obj[key]);
}
// 把他们变成用&连接的字符串,返回
return ret.join('&');
}
function myAjaxGet(url, obj, success, error) {
let btn = document.querySelector("button");
btn.onclick = function (val) {
// 0.将obj变成字符串
let str = obj2str(obj);
// 1.创建异步对象
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和地址
xmlhttp.open("GET", url + "?" + str, true);
/*
open的参数
01 请求方式 GET / POST
02 请求地址
03 同步false/异步true ajax固定异步,必须是true
*/
// 3.发送请求
xmlhttp.send();
// 4.监听状态
xmlhttp.onreadystatechange = function (val2) {
// 5.进行处理
// 5.1当消息传输完成时才进行处理
if (xmlhttp.readyState === 4) {
// 5.2判断消息是否正常传输,没有发生错误
if (
(xmlhttp.status >= 200 && xmlhttp.status < 300) ||
xmlhttp.status === 304
) {
// 5.3对成功状态进行处理
success(xmlhttp);
} else {
error(xmlhttp);
}
}
};
};
}
<script src="./get_wrap2.js"></script>
<script>
myAjaxGet(
"get2.php",
{
name: "Joe",
age: "18",
fk: 0,
},
(xhr) => {
alert(xhr.responseText);
},
(xhr) => {
console.log("error!");
}
);
</script>
亿点细节
-
请求响应的时间不定,为了防止时间过长应该设定一个最长时间,超时就停止请求
-
url中不能出现中文,因此要用JS方法将其转码
修改;
1.myAjaxGet方法新增参数limitTime
2.方法内新增timer变量用于接收定时器id
3.方法内新增定时器,定时器时间为limitTime
4.方法内进行url拼接的地方 URL要用encodeURIComponent方法转码
5.obj2str方法中key和val在push前要用encodeURIComponent方法转码
function obj2str(obj) {
/*
obj的格式为 key:val
将它转成字符串 key1=val1&key2=val2 的形式
*/
// 将用于兼容IE的时间随机数也放进来一起处理
obj.t = new Date().getTime();
let ret = [];
// 形成[key1=val1,key2=val2]形式的数组
for (key in obj) {
ret.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
// 把他们变成用&连接的字符串,返回
return ret.join('&');
}
function myAjaxGet(url, obj, limitTime, success, error) {
let btn = document.querySelector("button");
btn.onclick = function (val) {
// 0.将obj变成字符串
let str = obj2str(obj);
// 1.创建异步对象
var xmlhttp, timer;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和地址
xmlhttp.open("GET", encodeURIComponent(url) + "?" + str, true);
/*
open的参数
01 请求方式 GET / POST
02 请求地址
03 同步false/异步true ajax固定异步,必须是true
*/
// 3.发送请求
xmlhttp.send();
// 4.监听状态
xmlhttp.onreadystatechange = function (val2) {
// 5.进行处理
// 5.1当消息传输完成时才进行处理
if (xmlhttp.readyState === 4) {
//传输完成,清除定时器
clearInterval(timer);
// 5.2判断消息是否正常传输,没有发生错误
if (
(xmlhttp.status >= 200 && xmlhttp.status < 300) ||
xmlhttp.status === 304
) {
// 5.3对成功状态进行处理
success(xmlhttp);
} else {
error(xmlhttp);
}
}
};
// 若超时则停止请求
timer = setInterval(() => {
console.log('timer out!');
xmlhttp.abort();//终止请求
clearInterval(timer);
}, limitTime);
};
}
<script src="./get_wrap3.js"></script>
<script>
myAjaxGet(
"get2.php",
{
name: "Joe",
age: "18",
fk: 0,
chinese: "你好",
},
3000,
(xhr) => {
alert(xhr.responseText);
},
(xhr) => {
console.log("error!");
}
);
</script>
- 注意事项
url中只能是字母、数字、下划线、ASCII码,其他的都要转码
Ajax-POST方法
基本用法
- 无表单数据
xmlhttp.open("POST","demo_post.asp",true);
xmlhttp.send();
- 有表单数据
1.在open和send之间加上setRequestHeader方法
2.将要传递的表单数据作为send的参数传递
xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");
封装POST,并实现同时具有两种模式的方法
修改:
1.方法名为myAjax,增加参数 method 接收传输方式
2.方法内新增if判断,是GET方法还是POST方法
3.GET方法沿用前面封装,POST方法按照上面有表单数据来封装
function obj2str(obj) {
/*
obj的格式为 key:val
将它转成字符串 key1=val1&key2=val2 的形式
*/
// 将用于兼容IE的时间随机数也放进来一起处理
obj.t = new Date().getTime();
let ret = [];
// 形成[key1=val1,key2=val2]形式的数组
for (key in obj) {
ret.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
// 把他们变成用&连接的字符串,返回
return ret.join('&');
}
function myAjax(method, url, obj, limitTime, success, error) {
let btn = document.querySelector("button");
btn.onclick = function (val) {
// 0.将obj变成字符串
let str = obj2str(obj);
// 1.创建异步对象
var xmlhttp, timer;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
if (method === "GET") {
// 2.设置请求方式和地址
xmlhttp.open("GET", encodeURIComponent(url) + "?" + str, true);
/*
open的参数
01 请求方式 GET / POST
02 请求地址
03 同步false/异步true ajax固定异步,必须是true
*/
// 3.发送请求
xmlhttp.send();
// 4.监听状态
xmlhttp.onreadystatechange = function (val2) {
// 5.进行处理
// 5.1当消息传输完成时才进行处理
if (xmlhttp.readyState === 4) {
//传输完成,清除定时器
clearInterval(timer);
// 5.2判断消息是否正常传输,没有发生错误
if (
(xmlhttp.status >= 200 && xmlhttp.status < 300) ||
xmlhttp.status === 304
) {
// 5.3对成功状态进行处理
success(xmlhttp);
} else {
error(xmlhttp);
}
}
};
// 若超时则停止请求
timer = setInterval(() => {
console.log('timer out!');
xmlhttp.abort();//终止请求
clearInterval(timer);
}, limitTime);
} else {
// 2.设置请求方式和地址
xmlhttp.open("POST", encodeURIComponent(url), true);
/*
open的参数
01 请求方式 GET / POST
02 请求地址
03 同步false/异步true ajax固定异步,必须是true
*/
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 3.发送请求
xmlhttp.send(str);
// 4.监听状态
xmlhttp.onreadystatechange = function (val2) {
// 5.进行处理
// 5.1当消息传输完成时才进行处理
if (xmlhttp.readyState === 4) {
//传输完成,清除定时器
clearInterval(timer);
// 5.2判断消息是否正常传输,没有发生错误
if (
(xmlhttp.status >= 200 && xmlhttp.status < 300) ||
xmlhttp.status === 304
) {
// 5.3对成功状态进行处理
success(xmlhttp);
} else {
error(xmlhttp);
}
}
};
// 若超时则停止请求
timer = setInterval(() => {
console.log('timer out!');
xmlhttp.abort();//终止请求
clearInterval(timer);
}, limitTime);
};
}
}
<script src="./get_post.js"></script>
<script>
myAjax(
"POST",
"get2.php",
{
name: "Joe",
age: "18",
fk: 0,
chinese: "你好",
},
3000,
(xhr) => {
alert(xhr.responseText);
},
(xhr) => {
console.log("error!");
}
);
</script>
仿照jQuery的Ajax 完善封装
method的大小写问题
只能传大写的POST和GET才能正常使用
解决方法
在if判断的时候全部先转为小写再判断
if(method.toLowerCase()==='get'){
..
}else{
..
}
参数顺序问题
必须按照顺序接收参数,否则无法正常使用
解决方法
将参数改为一个对象,这样使用其中各属性都是 对象.属性 的方式,不需要关注其顺序(具体实现略)
声明
参数 function myAjax(option){..}
使用 option.url
option.method
...
调用
myAjax({
url:'xx',
method:'xx',
...
});
Ajax数据传输
- 问题提出
服务器如果返回的是简单的字符串数据,会难以区分和使用(比如哪里是用户名哪里是密码)。
简单使用如 “|” 之类的字符进行分割容易引起错误(比如原本数据里就带|符号)
所以需要一种格式化的数据传送方式
Ajax-xml解析
xml格式
- 头部
<?xml version="1.0" encoding="UTF-8" ?>
- 标签
所有数据都要放到一个 【根标签】 内,且所有标签的名字都是【自定义】的
<person>
<name>alex</name>
<age>18</age>
</person>
服务端php返回xml格式
头部必须加
header("content type:text/xml: charset-utf 8")
返回内容
echo file_get_contents("user.xml");
前端解析xml格式数据
xml格式和html格式的标签获取方式一致
res=xhr.responseXML //获取xml数据
res.querySelector('name') ==> <name>alex</name>
res.querySelector('name').innerHTML ==> alex
前端解析JSON数据
接收:
str=xhr.responseText
处理:
str=JSON.stringify(obj) 对象转成JSON字符串形式
obj=JSON.parse(str) 字符串转成JSON对象形式
使用:
obj.name
obj.age
IE兼容性:
引入JSON2.js文件
-
JSON比xml更有优势,体积小、简洁、操作简单
-
JSON处理注意事项
后端可能返回的是非标准的JSON字符串
比如 对象中key没有用双引号
这样的字符串无法使用JSON.parse解析成对象
解决:使用eval来解析
var obj=eval("("+str+")");
用法:eval解析时要将str用()括起来
既可以解析JSON字符串,也可以解析非标准JSON字符串