express 使用ajax
1. 使用XMLHttpRequest
后台代码:
const express = require('express')
const app = express()
app.use(express.static("public")) // 静态资源目录
// FOR:"Content-type":"application/x-www-form-urlencoded"
app.use(express.urlencoded({extended: false }));
// FOR:"Content-type":"application/json"
// app.use(express.json())
app.post('/calc', (req, res) => {
console.log(req.body) // MUST ADD app.use(...)
setTimeout(()=>res.send(`<div style="background-color:tomato;
border-radius:50%;width:${req.body.w}px;height:${req.body.h}px"/>`), 1000)
})
app.listen(8080)
在public/index.html
里面可以搞一个按钮来发送ajax请求(可以使用JQUERY):
<!DOCTYPE html>
<html>
<head> <meta charset="utf-8"><title></title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<form action="post">
<div>宽:<input type="text" id="w" placeholder="input width"></div>
<div>高:<input type="text" id="h" placeholder="input height"></div>
<div><input type="button" id="calc" onclick="Calc()" value="calc" /></div>
</form>
<div id="result"></div>
</body>
<script>
function Calc() {
let xhr = new XMLHttpRequest() // 创建XHR
let w = parseFloat(document.getElementById('w').value)
let h = parseFloat(document.getElementById('h').value)
xhr.open('post', '/calc', true)// 方法,路径,异步
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
//xhr.responseType = "json";// 响应BODY的 content-type类型:json/text...
xhr.onload = function (e) {
if(this.status==200)//HTTP status code
// 注意:不是oReq.responseText
document.getElementById("result").innerHTML = this.response
}
xhr.send(`w=${w}&h=${h}`);
//xhr.setRequestHeader("Content-type", "application/json");
//xhr.send(JSON.stringify({w, h})); // use JSON format
document.getElementById("result").innerHTML = `WAITING...` // waiting...
console.log("OK")
}
// 方法二
/*
$("#calc").on('click', () => {
let w = $("#w").val()
let h = $("#h").val()
$.ajax({
type: 'post',
url: '/calc', // xhr.open('post','/calc',true)
contentType: 'application/json', // xhr.setRequestType('application/json')
data: JSON.stringify({w,h}), // xhr.send(JSON.stringify({name}))
success: function (response) { // xhr.onload =
console.log(response)
$("#result").innerHTML = (response)
},
error: function (e) { } // xhr.onerror
})
})
*/
</script>
</html>
2 使用表单FormData & Fetch API
重点在于FormData
和formidable
的配合使用,注意不要使用form的action/onsubmit,会导致AJAX返回数据看不到。
npm install formidable -S
<form id="form1" style="width:245px">
用户名:<input type='text' name="name" placeholder="input your name" />
<br><br>
密码:<input type='password' name="pswd" placeholder="input your password"/>
<br><br>
<input type="button" onclick="Send()" value="send" />
</form>
<script>
async function Send() {
var form = document.forms.namedItem("form1");
//将htmL表单转换为FormData表单对象
var formData = new FormData(form);
console.log(formData.get("image_uploads"))
let res = await fetch('/login', {
method: 'post',body:formData // json需要转字符串;这里可以直接传递formdata
})
let json = await res.json() // text() blob()
console.log(json)
}
</script>
后台使用formidable自动解析req:
const express = require('express')
const formiable = require('formidable')
const app = express()
app.listen(8080)
app.use(express.static('public'))
app.post('/login', (req, res) => {
let form1 = formiable({
uploadDir: path.join(__dirname, "uploads"), //设置上传目录
multiples: true, // 多文件
allowEmptyFiles: false, // 不允许空文件
keepExtensions: true //保持原有扩展名
});
form1.parse(req, (err, fields, files) => {
console.log(fields.name,fields.pswd)// 2.fileds即form1数据{name,pswd}
//...
})
})
3.上传文件
上传文件和普通的表单并无不同:
<form id="form1" >
上传头像<input type="file" required multiple
id="file1" accept=".jpg, .jpeg, .png" name="image_uploads">
<input type="button" onclick="Send()" value="send" />
<img id="res"/>
</form>
<script>
function Send() {
var form = document.forms.namedItem("form1");
//将htmL表单转换为FormData表单对象
var formData = new FormData(form);
console.log(formData.get("image_uploads"))
let xhr = new XMLHttpRequest()
xhr.open('post', '/upload', true);
xhr.responseType = 'json'
xhr.onload = function () {//3
if (this.status == 200) {
console.log(xhr.response)
document.getElementById('res').src = this.response
}
}
xhr.send(formData)// 1
}
</script>
后台处理一下files
字段即可:
app.post('/upload', async (req, res) => {
let form1 = formiable({
uploadDir: path.join(__dirname, "uploads"), //设置上传目录
multiples: true, // 多文件
allowEmptyFiles: false, // 不允许空文件
keepExtensions: true //保持原有扩展名
});
form1.parse(req, async (err, fields, files) => {
const multiples = Array.isArray(files.image_uploads); // 多文件
if (multiples) { //多个文件
const ret = []
for (let file of files.image_uploads) {
let oldFilename = file.filepath //本地路径
const imgBase64 = await readFileBase64(oldFilename)
ret.push(imgBase64) //【base64 image】
}
return res.send(JSON.stringify(ret))
} else if (files.image_uploads) { // 单文件
console.log("SDFSD",files.image_uploads)
let oldFilename = files.image_uploads.filepath
// 方法1,使用URL,发送一个 path url!
// res.send(files.attrName.filepath.split('public')[1])
const imgBase64 = await readFileBase64(oldFilename)
return res.send({path:imgBase64})
}
else res.send("[]")
})
})
// 图片文件转为base64图片
async function readFileBase64(file) {
try {
const res = await fs.readFile(file);
const mtype = mime.getType(file)
var base64str = res.toString('base64');
// START WITH `data:image/png;base64,`
return `data:${mtype};base64,${base64str}`
} catch (err) {
console.error(err);
}
return null;
}
4. 跨源资源共享 CORS
出于安全性,浏览器限制脚本内发起的跨源HTTP请求(script/img/iframe标签除外)
解决方法分为前端和后端。这里使用前端jsonp
方案(后端使用request包,类似爬虫方案)。首先前台代码使用<script>
跨域访问服务器localhost:3001
<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>@localhost:3000</title>
</head>
<body>
<script>
function fn(data){console.log(`fn return: ${data}`)}
</script>
<script src="http://10.201.17.100:3001/jsonp?a=1&b=2"></script>
</body>
</html>
后台3000端口模拟本地服务器A,3001模拟服务器B,代码如下:
//服务器A
const express = require('express')
const app = express()
app.listen(3000)
app.use(express.static('public'))
//服务器B
const express = require('express')
const app = express()
app.listen(3001)
app.use(express.urlencoded({extended:false}))
app.get('/jsonp', (req, res)=>{
console.log(req.query)
let c = parseInt(req.query.a) + parseInt(req.query.b) // 计算 a+b
res.send(`fn(${c})`)
})