一、获取提交的数据
GET
1.接收GET请求的数据:
ctx.request.query 或者 ctx.query
req的缩写:httpRequestMessage ==>前端请求的数据包
egg后端get请求的参数:
this.ctx.request 前端的数据包放在这个对象里面,不再是原来的url了,已经解析好了是一个对象,可以>直接点语法。
data是一个对象
var data = this.ctx.request.query
GET请求的缺点:
1、参数会拼接到url中,数据会拼到网址中,发给后端,所以就不安全
2、但是它速度快
3、所以就适用于没有隐私、密码等
1、ajax-get
==>xhr.open("GET",url)
GET请求传参数给后端
后端返回的数据 前端是xhr对象接受了,程序员用js语言来使用返回的数据
index.html中:
var searvalue=document.getElementById("seariput").value
var xhr=new XMLHttpRequest()
var url=`http://192.168.6.60:7001/get1?count=20&keywords=${searvalue}`
xhr.open("GET",url)
xhr.send()
xhr.onreadystatechange=()=>{
if(xhr.readyState==4&&xhr.status==200){
console.log(xhr.responseText)
}
}
但是一般做项目不用原生AJAX代码,一般用axios。
2.axios-get
它是ajax技术封装出来的
后端返回的数据 前端是xhr对象接受了,程序员用js语言来使用返回的数据
axios接收的第二个参数是一个对象
index.html中:
var searvalue=document.getElementById("seariput").value
var url=`http://192.168.6.60:7001/get1`
axios(url,{params:{count:20,keyw:searvalue}})
.then(res=>console.log(res))
{params:{count:20,keyw:searvalue}}这是一个对象,如何将一个对象转为querystring ==>
function myaxios(url,obj){
let arr=Object.keys(obj.params) //取出对象的属性名
let querystring=""
for(let i=0;i<arr.length;i++){
querystring+=arr[i]+"="+obj.params[arr[i]]
}
querystring&&(url+"?"+querystring)
// 然后去请求它url
}
3.浏览器的地址栏-get 浏览器的地址栏==>[只能]发送get请求, 不能做POST请求
接受的数据会直接读取渲染,如果解析失败会下载
比如:public里面有有一个test.rar==>输入网址:192.168.6.60:70001/public/test.rar。浏览器就会直接下载这个压缩包
4.a标签的href属性-get 也[只能]发get请求,并且是点击事件触发了默认事件才会发送get请求
发送网络请求给href的网址,后端返回的数据,接受的数据会直接读取渲染,如果解析失败会下载
例子:(点击点我后,就会下载这个test.rar)
index.html中:
home.js中:(readFileSync代表同步)
async download() {
this.ctx.body=fs.readFileSync(__dirname+'/../public/test.rar')
}
5.img-src-get
[只能]发get请求 返回的数据渲染成图片 如果非图片编码就会 "碎裂"
img.οnlοad=()=>{}
6.link-href-get
[只能]发get请求 返回的数据按照功能使用 (比如css、js等等)
7.form表单-action-get
发送GET/POST/DELETE等等给action属性对应的url 发送请求
1.用户点击了提交按钮或者触发表单的提交事件
2.get请求会把form中的数据全部解析为url的querystring
3.返回的数据 同a标签,比如target
例子:
index.html中
(input中 的name就相当于querystring的key值,输入框的value就相当于key后面的属性值)
<!-- aaa=100&bbb=200 -->
<form method="GET" action="http://192.168.6.60:7001/login" target="_blank">
<input type="text" name="a"> //用户输入框内容为:1
<input type="text" name="b"> //用户输入框内容为:2
<input type="submit" value="login">
</form>
home.js中
async login(){
var data = this.ctx.request.query
console.log(k)
this.ctx.body="6666"
}
}
结果:前端网页会打印6666。后端会打印: {a:'1‘,b:'2'}
POST
不要把用户的隐式数据 直接拼接到url中发送给后端,应该转为暗文发送==> 用POST
如果有"大量"的数据(图片、视频)发给后端==> 用POST
ctx.request.body 而不是 ctx.body
2.1 post请求时,会有安全验证问题,简单的处理方式是关闭安全验证:
config/config.default.js文件 ==> 关闭csrf
config.security={
csrf:{
enable:false
}
}
2.2 post数据默认大小是100kb 如需调整可在 config/config.default.js 中覆盖框架的默认值:
config/config.default.js文件
module.exports = {
bodyParser: {
jsonLimit: '1mb', //JSON字段
formLimit: '1mb', //文件
},
};
get请求:(下面两句代码是等价的)
axios(url,{params:{userid:123,pwd:123}})
axios.get(url,{params:{userid:123,pwd:123}})
post请求:
axios.post(url,{userid:123,pwd:123})
.then(res=>console.log(res))
get和post请求的区别:
1、get请求会把params后面的对象解析到网址中
2、post会把对象变成暗文
例子:
public / index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src='https://s1.pstatp.com/cdn/expire-1-M/axios/0.19.2/axios.js'></script>
</head>
<body>
<h1>post请求</h1>
账号:<input type="text" id="userid"> <br>
密码:<input type="text" id="pwd"><br>
<button onclick="fn()">登录</button>
<!-- <form action="" enctype=""></form> -->
<!-- enctype有三个内容可选:
其中有一个就是下面AJAX代码中的setRequestHeader的application/x-www-form-urlencoded -->
<script>
function fn() {
//不要把用户的隐式数据 直接拼接到url中发送给后端
//应该转为暗文发送 用POST
var xhr = new XMLHttpRequest()
var url = "http://192.168.6.60:7001/post1"
xhr.open("POST", url, true)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");//规定数据包的编码格式
xhr.send(`userid=${userid.value}&pwd=${pwd.value}`)
//send这个函数接受字符串:querystring这种格式的字符串(比如:"pwd=123&userid=123")
//前提条件:
//如果是"POST",就会把这个请求的数据放在"请求数据包"-HTTPRequestMessage 的请求体中的
//如果是"GET",不会报错 但是也并不会把这个数据拼接到url中发送
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText)
}
}
var url = "http://192.168.6.60:7001/post1"
}
</script>
</body>
</html>
controller / home.js
'use strict';
const Controller = require('egg').Controller;
const fs = require("fs")
const path = require("path") //path模块,有一个方法basename
//path.basename("asdd/assd/s/dfsd/fg.jpg")==>最后结果为"fg.jpg"
class MyController extends Controller {
async get1() {
//req httpRequestMessage
//1.egg后端get请求的参数:
var k = this.ctx.request.query
console.log(k, 1111)
this.ctx.body = {
info: "get1接口的数据"
}
}
async post1() {
//1.前端POST发送给egg的参数字段
let obj=this.ctx.request.body //前端发过来的数据包的请求体
let query=this.ctx.request.query
console.log(obj,query)
this.ctx.body={info:"登录成功",res:obj} //this.ctx.body给前端返回数据
}
async post2(){
//1.前端POST发送给egg的参数字段
let ziduan=this.ctx.request.body
//2.前端POST发送给egg的参数文件
let f=this.ctx.request.files
console.log(ziduan,f)
//f打出来是数组,里面有field、filename、filepath等等
if(f[0]){ //确保有文件
let oldpath=f[0].filepath //文件的路径
let fname=path.basename(oldpath) //把文件的名字取出来
let newpath=__dirname+"/../public/upload/"+fname
fs.renameSync(oldpath,newpath) //Sync就是同步的意思
}
this.ctx.body={info:"注册成功6666"}
}
}
module.exports = MyController;
public / POSTfile.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src='https://s1.pstatp.com/cdn/expire-1-M/axios/0.19.2/axios.js'></script>
</head>
<body>
账号:<input type="text" id="userid"> <br>
密码:<input type="text" id="pwd"><br>
选择头像 <input type="file" id="f1" multiple>
<!-- multiple选多个文件,最多上传9个 -->
<img src="#" id="box">
<button onclick="fn()">登录</button>
<script>
//如果有"大量"的数据发给后端 用POST
function fn() {
//把要给后端发送的"大量"数据==>文件 处理成表单数据
var f1 = document.querySelector("#f1")
//f1有一个属性,files,它是一个类数组
var userid=document.querySelector("#userid")
var pwd=document.querySelector("#pwd")
var fdata = new FormData() //创建一个对象==>表单数据
fdata.append("userid", userid.value) //字段
fdata.append("pwd", pwd.value) //字段
fdata.append("touxiang", f1.files[0]) //就取一张图片 (文件)
//将用户所选的图片文件显示到网页上
var img1=window.URL.createObjectURL(f1.files[0]) //创建网址
console.log(img1) //打印出来是用户传入图片的网址
var box=document.querySelector("#box")
box.src=img1
var url = "http://192.168.6.60:7001/post2"
axios.post(url, fdata) //表单中有字段和文件,所以后端就要写字段和文件的代码
.then(res => console.log(res))
}
</script>
</body>
</html>
接收动态路由参数
在定义路由匹配路径的时候:
app.get('/click',function(req,res){
res.send('click');
})
单一的固定静态url,满足不了大量的动态处理,可以把代码改为:
app.get('/click/:id',function(req,res){
var id = req.params.id;
res.send();
})
像:id这样的正则会被放到req.params对象中。
var arr = {
"beijing":{
"mary":"my name is mary"
},
"shanghai":{
"tony":"my name is tony"
}
}
app.get('/click/:city/:name',function(req,res,next){
var info = arr[req.params.city][req.params.name];
if(!info) return next();//不存在的话最终会落入404中间件。
res.send('description',info);
})
这样就可以满足一些动态的请求。
某些正则表示可以直接用在路径中,
比如要用同一个路由处理 /user和/username 可以这样写:
app.get('/user(name)?',function(req,res){
res.send('user');
})
处理请求:
res.query //处理get请求;
res.body //处理post请求
res.params //处理get和post请求,但是查找的优先级为:params->body->query
二、获取上传的文件
1.egg必须启用 file 模式
(如果后端要接收文件,必须开启文件模式)
config/config.default.js文件
config.multipart = {
mode: 'file',
};
2.前端发送文件
2.1 表单
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="email" name="email" id="email">
<input type="password" name="password" id="password">
<input type="file" name="touxiang" id="touxiang">
<input type="submit" value="上传">
</form>
2.2 ajax
let data=new FormData()
data.append("email",email.value)
data.append("password",password.value)
data.append("touxiang",touxiang.files[0])
axios.post(url,data).then((res)=>{})
3.egg接受文件 ctx.request.files[0]
对象里面有上传的文件信息,主要包括文件的临时保存路径文件的字段名大小等等
一般情况文件的临时保存路径在c盘的temp文件夹中 我们需要自己处理移动到项目文件夹中
文件的名称是被修改过的哈希值命名的,需要自己处理修改文件名
注意点:fs模块的拷贝方法没有跨盘限制,rename方法有跨盘限制的bug
async file() {
console.log(this.ctx.request.files);
console.log(this.ctx.request.body);
console.log(this.ctx.request.query);
const { ctx } = this;
const file = ctx.request.files[0];
let to = __dirname+"/../public/upload/"+ file.filename
fs.renameSync(file.filePath,to)
// 返回上传图片的网址
ctx.body = `http://localhost:7001/public/upload/${file.filename}`;
}
三、常见的网络请求
1)目前能做POST请求的只有两个:AJAX、form表单
2)能做网络请求的技术有哪些:
网络请求的目的==> 给后端发数据、接收到后端传过来的数据、完成前后端交互
(前端给后端发送字段==>只能放在网址中,也就是只能发送GET)
(发送文件是放在请求体中,发送暗文)
地址栏: 地址栏输网址==>没有跨域限制 默认是get请求
2、标签:
1) 这些都是发送的GET请求:
1、img-src 没有跨域限制 默认是get请求 会启用绘制引擎去按照img资源的编码进行渲染
2、link-href
3、 **-url
(前三个都是自发的进行网络请求,当运行到这一行就会请求)
4、 a-href
5、script-src (V8会去运行,或者其它浏览器会运行)
没有跨域限制 默认是get请求 会启动js引擎去执行js代码 如果返回的数据的编码不是标准的js编码 就运行不了 如果返回的数据的编码是标准的js编码 就正常运行
(a link : href==>没有跨域限制 默认是get请求 它的请求功能是浏览器做的 而且使用数据的功能也是浏览器做的)
2) 这些都是发送的POST请求:
1、form-action-submit(两种触发方式:点击后调用函数、用js代码来操作)
form: action==>没有跨域限制 get/post请求 它的请求功能是浏览器做的 而且使用数据的功能也是浏览器做的''
2、AJAX-open-send
ajax: 无论工具库还是原生代码 都有跨域限制 get/post请求 请求的数据自己使用(xhr.responseText)
GET:发字段
axios(url?xx=123)
axios.get()
后端接收GET数据:
this.ctx.request.query
POST:发字段
axios.post(url,{pwd:123,age:19})
后端接收POST数据:
this.ctx.request.body
POST:发字段和文件
var fdata=new FormData()
fdata.append("pwd",1234)
fdata.append("email",1234)
fdata.append("touxiang1",f1.files[0])
fdata.append("touxiang2",f1.files[1])
fdata.append("touxiang3",f1.files[2]) (最多9个)
axios.post(url,fdata)
后端接收POST字段数据:
this.ctx.request.body
后端接收POST文件数据:
this.ctx.request.files 数组中是文件信息对象 filepath
特别提醒
post请求传递的文件图片默认保存在c盘中,如果你的软件不是装在c盘运行,需要将post请求的字段和文件转化,并且将图片位置移动到你所在的盘的文件路径中
'use strict';
const Controller = require('egg').Controller;
const fs = require("fs")
const path = require("path")
var svgCaptcha = require('svg-captcha');
class ResgiterController extends Controller {
async rootAddGoods(){
let ziduan=this.ctx.request.body
let f=this.ctx.request.files
// console.log(ziduan,f)
let oldpath=f[0].filepath
let newpath=__dirname+"/../public/goods/"+path.basename(oldpath)
fs.renameSync(oldpath,newpath)
await fs.copyFileSync(oldpath,newpath)
fs.unlinkSync(oldpath)
ziduan[f[0].field]="/public/goods/"+path.basename(oldpath)
//ziduan.img="/public/goods/"+path.basename(oldpath)
let re1=await this.ctx.service.root.addgoods(ziduan)
this.ctx.body={info:"添加商品成功",code:2009}
}
}
module.exports=ResgiterController