DaZeng:Nodejs——express

21 篇文章 1 订阅
1 篇文章 0 订阅

准备

安装node,npm 是nodejs package manage,包管理器。主要用于安装依赖包,执行一些命令。

如果安装很慢,修改Npm下载包的路径 :
从taobao下载,执行以下命令;
npm config set registry https://registry.npm.taobao.org

如果要想运行别人的代码,就在当前package.json文件位置,打开命令提示行。输入npm install,自行安装所有依赖包。

node -v,查看node版本号
npm -v,查看Npm的版本号。
npm init -y 初始化项目,生成项目的配置文件package.json 安装 express框架
npm install express --save 或 npm i express --save

创建app.js文件,使用node app.js启动服务器。
在这里插入图片描述

了解

common.js (同步的模块加载) , require.js库(AMD异步的模块加载);参考文件中间件模块http状态码
100-102 消息
200-207 成功: 200,
300-307 重定向 302,304,
400-449 请求错误 400,404,415 ,
500-600 服务器错误 500

请求头的类型content-type:
以application开头的媒体格式类型:

application/xhtml+xml :XHTML格式
application/xml: XML数据格式
application/atom+xml :Atom XML聚合格式
√ application/json: JSON数据格式
application/pdf:pdf格式
application/msword : Word文档格式
√ application/octet-stream : 二进制流数据(如常见的文件下载)
√ application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
√ multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

npm i morgan --save 安装日志模块

访问服务器的方法:
-- 本机访问:
127.0.0.1:8000
localhost:8000
-- 内网IP:
172.16.2.56:8000

npm i serve-favicon -D  (--save-dev) 生成项目依赖 网站小图标
npm i serve-favicon --save  (生成项目依赖) 网站小图标

npm uninstall 中间件名称  卸载中间件

app.js

基础配置

// 1.直接引用 express 模块;
const express = require("express");
// 2.创建一个应用程序服务器;web服务器;
const app = express();

// 3.调用set(); 设置Port
// 0-1024范围,是操作系统预留给各种系统应用程序的端口,1024以后的,是其它软件厂商的程序的端口。

app.set("port", 8000)
// __dirname,就是当指向当前项目环境的工作空间目录,即root
// express.static(),设置服务器中,网站静态资源的路径 。(html,css,js,图片等资源)
// app.use():表示配置、设置、使用某一个中间件。
// 中间件:表示可以实现某一个问题的模块。
app.use(express.static(__dirname + '/public'))

// 4.调用监听方法:listen();
app.listen(app.get('port'), ()=>{
    console.log("你人生第架服务器,正在运行中..");
})

加入router和中间件

const express = require("express");
const morgan = require("morgan");
const serveFavicon = require("serve-favicon");
const userRouter = require("./route/userRouter")  //引用用户功能模块,一定要回加"./",不然找到模块!!
const bodyParser = require("body-parser");  // 处理POST,PUT,DELETE,OPTION请求的中间件,除GET以外的请求

const app = express();//创建一个application服务器;

app.use(morgan("dev")); // 配置日志系统
app.use(serveFavicon(__dirname+"/public/favicon.ico")); //设置网站的小图标

// 在路由配置之前,配置bodyParser
app.use(bodyParser.urlencoded({extended:false})); //处理请求头为 application/x-www-form-urlencoded时;如表单默认的请求头;
app.use(bodyParser.json()); //处理请求头为 application/json时;如AJAX请求时,参数是一个对象时;
/*
	extended选项允许您在使用querystring库(when false)或使用qs库(when true)解析URL编码的数据之间进行选择。
	querystring只能转换一层JSON对象的格式 ;{a:1,b:2}
	qs可以转换多层JSON对象的格式 :{a:1,b:2,c:{x,y,z:{w,h}}}
	qs需要单独安装
*/

// 在设置静态资源目录之前,配置路由:
app.use("/", userRouter);  //以“/”开头的请求,都先去userRouter进行拦截处理;

app.use(express.static(__dirname+"/public")); //设置静态资源目录
app.set('port',8000)  //设置访问的端口
// app.get("port")  // 获取指定的属性的值;
// 监听服务器提供服务的端口;
app.listen(app.get("port"), ()=>{
    console.log("服务器正常运行中, http://127.0.0.1:8000 ")
})

router和mysql

npm i mysql --save //安装mysql

配置mysql,连接mysql服务器,执行mysql命令,关闭mysql连接;

//处理POST请求方式,需要安装 body-parser中间件;
npm i body-parser --save
----------------------------------------------------------------------
const express = require('express')
const router = express.Router() // 调用Router(),返回一个空的路由对象回来。
const mysql = require('mysql')
//公开路由对象;
module.exports = router;

// router.route("/login")
// .get((req,res)=>{
//     let user = req.query
//     console.log("get user",user)
// })
// .post(function(req,res){
//     let user = req.body
//     console.log("post user",user)
// })

router.get("/login", function (req, res) {
    let user = req.query;
    console.log(user)
    if(user.name.length != 0 && user.pass.length != 0){
        let con = mysql.createConnection({
            host:'localhost',
            user:'root',
            password:'*******',
            port:3306,
            database:'w240'
        })
        // 打开数据库的连接;连接到数据库;
        con.connect()
        let sql = "SELECT * FROM users WHERE user = ? AND pass = ?"
        // mysqlConnection.query(sql,param,callback);
        // 'insert into n_user value(null,?,?);'在mysql语句中,凡是变量的地方,用?来替换,防止 SQL注入漏洞产生。
        //  ??和param变量的数量是一一对应;
        con.query(sql,[user.name,user.pass],function(error,data){
            console.log("error-------",error); //error------- null
            console.log("data-------",data);  //data------- []
            if(data.length === 1){
            // console.log("error:",error);
                //操作MYSQL失败时,error不为Null. 成功是为null; 
                // console.log("data:",data); 
                // 操作MYSQL失败时,data是undefined
                // 成功时,是一个object对象,如果是select语句,就是一个数组对象;
                res.redirect('pages/main.html')
            }else{
                res.redirect('index.html')
            }
        })
        con.end()
    }
})


//post请求时,获取请求的参数,通过request.body来获取 
router.post('/register',function(req,res){
    let user = req.body //body中的属性名,来自于form中,input等的name标签属性的值;
    if(user.name.length != 0 && user.pass.length != 0){
        let con = mysql.createConnection({
            host:'localhost',
            user:'root',
            password:'**********',
            port:3306,
            database:'w240'
        })
        con.connect()
        let sql = " insert into users value(null,?,?)"
        con.query(sql,[user.name,user.pass],function(error,data){
            console.log("error-------",error); //error------- null
            console.log("data-------",data);  //data------- []
            if (error == null) {
                // res.send("注册成功")
                res.redirect("pages/main.html")  //重定向到另个页面,访问成功注册的页面。 
            } else {
                // res.send("注册失败")
                res.redirect("index.html") //注册失败,重写向到失败页面
            }
        })
        con.end()

    }
    
})

Form表单提交请求

//html  GET、POST
 <form action="/login"  method="GET">
        <label for="">
            用户名:
            <input type="text" name="name" id="">
        </label>
        <label for="">
            密码:
            <input type="password" name="pass" id="">
        </label>
        <button type="submit">提交</button>
    </form>

<form action="/register" method="POST">
        <label for="">
            用户名:
            <input type="text" name="name" id="">
        </label>
        <label for="">
            密码:
            <input type="password" name="pass" id="">
        </label>
        <button type="submit">提交</button>
    </form>

ajax的使用

//html
 <label for="">
     user:
     <input type="tel" name="name" id="n1">
 </label>
 <label for="">
     pass:
     <input type="password" name="pass" id="p1">
 </label>
 <button type="button" id="login">登录</button>

 <hr>

 <label for="">
     user:
     <input type="tel" name="name" id="n2">
 </label>
 <label for="">
     pass:
     <input type="password" name="pass" id="p2">
 </label>

---------------------------------------------------------------------------------------------
//js
let loginbtn = document.getElementById('login')
let registerbtn = document.getElementById('register')

 loginbtn.onclick = () =>{
     localStorage.removeItem('user')
     let name = $('#n1').val()
     let pass = $('#p1').val()
     let user = {
         name,
         pass
     }
     console.log(user)
     $.ajax({
         type:'GET',
         url:'/login',
         data:user,
         success:function(res){
             console.log(res)
             if(res.state == 1){
                 localStorage.setItem('user',JSON.stringify(res.name))
                 alert('登陆成功')
                 window.location.href = './page/main.html'
             }
         }
     })
 }

 registerbtn.onclick = () =>{
     let name = $('#n2').val()
     let pass = $('#p2').val()
     let user = {
         name,
         pass
     }
     // $.ajax({
     //     type:'POST',
     //     url:'/register',
     //     data:user,
     //     success:function(res){
     //         console.log(res)
     //         if(res.state == 1){
     //             alert(`${res.msg}`)
     //         }
     //     }
     // })
     
      //原始ajax
     let xhr;
     if(window.XMLHttpRequest){
         xhr = new XMLHttpRequest();
     }else{
         xhr = new ActiveXObject("Microsoft.XMLHTTP")
     }
     xhr.open('post','/register',true)
     xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
     
     xhr.send(`name=${name}&pass=${pass}`)
     xhr.onreadystatechange = function(){
         if(xhr.readyState == 4 && xhr.status == 200){
             let res = JSON.parse(xhr.responseText)
             console.log(res)
             if(res.state == 1){
                 alert(`${res.msg}`)
             }
         }
     }

 }

配合nodejs的router配置:

const express = require('express')
const mysql = require('mysql')
const router = express.Router()


module.exports = router


router.route('/login').get((req,res)=>{
    console.log(req.query)
    let user = req.query
    console.log("get------->",user);
    if(user.name.length!=0 && user.pass.length!=0){
        let con = mysql.createConnection({
            host:'localhost',
            user:'root',
            password:'**************',
            database:'w240'
        })
        con.connect()
        let sql = 'SELECT user,pass FROM users WHERE user = ? AND pass = ?'
        
        con.query(sql,[user.name,user.pass],function(error,data){
            console.log("err",error);
            console.log("data",data);

            if(data.length == 1){
               
                // res.redirect('page/main.html')
                return res.json({
                    name:user.name,
                    msg:'登录成功',
                    state:1
                })
                
            }else{
                res.redirect('index.html')
            }
        })
    
        
        con.end()
    }
    
})


router.route('/register').post((req,res)=>{
    let user = req.body
    console.log("post------->",user);

    if(user.name.length!=0 && user.pass.length!=0){
        let con = mysql.createConnection({
            host:'localhost',
            user:'root',
            password:'***********,
            database:'w240'
        })
        con.connect()
        let sql = 'INSERT users VALUES(null,?,?)'
        
        con.query(sql,[user.name,user.pass],function(error,data){
            console.log("err",error);
            console.log("data",data);

            if(error == null){
                res.json({
                    msg:'注册成功!请登录',
                    state:1
                })
            }else{
                res.redirect('index.html')
            }
        })
    
    
        con.end()
    }

})

原生ajax

  1. 概念:
    AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
    AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
    AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。

创建AJAX的 XMLHttpRequest对象
let xhr;
if (window.XMLHttpRequest) {
// 非IE浏览器的支持写法;
xhr = new XMLHttpRequest();
} else {
// IE5/6 支持的写法:
xhr = new ActiveXObject(“Microsoft.XMLHTTP”)
}

向服务器发送请求
如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:
xhr.open(method,url,async);

method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)

xhr.send(string);

string:仅用于 POST 请求

setRequestHeader():当是POST请求时,必须设置请求头信息,不然后端无法获取参数的数据!!!
xhr.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);

get请求时:
xhr.open(‘get’,“url?key=value&key=value”,true)
xhr.send()

监听XMLHttpRequest 的状态:
xhr.onreadystatechange = function(){
readyState === 4 ,status === 200时,才会更新DOM。
}

readyState 属性的值:
存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪

status属性:200: “OK”,404: 未找到页面

responseText 获得字符串形式的响应数据。
responseXML 获得 XML 形式的响应数据。

AJAX实现的7个步骤:
1 创建AJAX XMLHttpRequest对象;
2. open(method, url,true);打开一个请求的链接(POST请求,添加请求头。)
setRequestHeader()
3. send(string || null);发起请求
4. 监听状态的变化
5. 判断状态的变化,并处理响应回来结果;
6. 写NODEJS后台的逻辑;
7. 回到前端页面中,更新页面的DOM数据或者页面的跳转等业务。

get请求数据
xmlhttp.open(“GET”,"/try/ajax/demo_get2.php?fname=Henry&lname=Ford",true);
xmlhttp.send();

post请求数据
xmlhttp.open(“POST”,"/try/ajax/demo_post2.php",true);
xmlhttp.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);
xmlhttp.send(“fname=Henry&lname=Ford”);

案例:
let xhr
if(window.XMLHttpRequest){
     xhr = new XMLHttpRequest()
 }else{
     xhr = new ActiveXObject('Microsoft.XMLHTTP')
 }
 xhr.open('get','/getlist',true)
 xhr.send()
 xhr.onreadystatechange = function(){
     if(xhr.readyState ==4 && xhr.status == 200){
         let res = JSON.parse(xhr.responseText)
         console.log(res);
     }
 }

封装mysql配置

新建mysql配置文件:

const mysql = require('mysql')

module.exports = {
    config:{
        host:'localhost',
        user:'root',
        password:'*************',
        port:3306,
        database:'w240'
    },
    query(sql,param,cb){
        let con = mysql.createConnection(this.config)
        con.connect()
        con.query(sql,param,cb)
        con.end()
    }
    
}

以登录为案例:在user.js引入mysql,直接使用mySql.query调用方法query。

const mySql = require('./mysql')

router.route('/login').get((req,res)=>{
    console.log(req.query)
    let user = req.query
    console.log("get------->",user);
    if(user.name.length!=0 && user.pass.length!=0){
                                                          
        let sql = 'SELECT user,pass FROM users WHERE user = ? AND pass = ?'
        let param = [user.name,user.pass]
        let cb = function(error,data){
            console.log("err",error);
            console.log("data",data);
            if(data.length == 1){
                return res.json({
                    name:user.name,
                    msg:'登录成功',
                    state:1
                })
            }else{
                res.redirect('index.html')
            }
        }

        mySql.query(sql,param,cb)
    }
    
})

封装抛出的mysql为一个promise对象

promise剖析传送门

const mysql = require('mysql')

module.exports = {
    config:{
        host:'localhost',
        user:'root',
        password:'Forgive22',
        database:'mirror',
        port:3306
    },
    query(sql,param){   
        return new Promise((resolve, reject) => {
            let con = mysql.createConnection(this.config);
            con.connect();
            con.query(sql, param, (err, data) => {
                if (err) { // fail=>{}
                    reject(err)
                } else { // ok => null
                    resolve(data) //返回数据库查询的结果
                }
            });
            con.end();
        });
    }
}

以动态渲染主导航和子导航为例使用mysql:

const express = require('express')
const mysql = require('./mysql')

const router = express.Router()

router.route('/getMenus')
.get((req,res)=>{
    let sql = "select * from m_menu";
    let menus = [];
    let summenus = []
    mysql.query(sql,[])
    .then((success)=>{
        menus = success
        let sql = "select * from m_submenu";
        return mysql.query(sql,[])
    })
    .then((success)=>{
        summenus = success
        res.json({
            status:200,
            msg:"成功",
            data:[menus,summenus]
        })
    })
    .catch((errorResult) => {
        console.log(errorResult);
        res.json({
            status: 40001,
            msg: "获取菜单数据失败",
            data: []
        })
    });

})


module.exports = router

Nodejs实现CORS跨域

使用的标准是CORS,即跨域资源共享。CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了只能同源使用的限制。

app.js配置:

// CORS配置跨域请求:
app.use('/*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    next();
})

当session遇上跨域

在一个跨域请求的项目中,需要存储提个session为后续的操作做一个判断依据:

结果获取到的都是null,查阅了相关资料,才了解到这是因为当进行跨域时,每一次请求都没有将sessinId带过去,服务器就认为是一个没有登录的新请求,都会在cookie里set一个新的sessionId,所以我之前存的值永远也取不到。

Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。即服务端用于区分特定用户的数据结构。一般的做法都是在客户端通过验证后,服务端将一个sessionId告诉客户端,在随后的通讯中,客户端将sessionId告诉服务端,用Cookie携带SessionID,服务器根据SessionID管理该用户会话、权限,服务端通过验证sessionId的方法来确认客户端的身份。这里面的核心就是session是在服务端管理的,将id交给客户端用作区分。
因此在跨域时,需要在各个环节上都要保证客户端的sessionid不能丢失,否则就会被服务端拦截,无法获取服务的问题。

解决方案:
ajax请求设置为如下:

$.ajax({
        url: commonUrl + url,
        type: 'post',
        data: JSON.stringify(obj),
        //加上 xhrFields及crossDomain
        xhrFields: { 
            withCredentials: true//允许带上凭据
        },
        crossDomain: true,
        //
        success:function(res){
        },
        error:function(){
        }
    });

后台都统一添加:

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));//处理跨域
response.setHeader("Access-Control-Allow-Credentials", "true");//表示是否允许发送Cookie

在一开始解决跨域时,我采用的是 response.setHeader(“Access-Control-Allow-Origin”, “*”) 处理跨域,表示接受任意域名的请求。

但是设置了response.setHeader(“Access-Control-Allow-Credentials”, “true”)后,就不能使用“*”。

不过要处理好跨域,可以直接设置允许请求的域名:response.setHeader(“Access-Control-Allow-Origin”, “域名名称”)。

session存储并设置cookie

安装express-session

npm i express-session --save

配置session

const expressSession = require("express-session");
app.use(expressSession({ //使用该配置后,req.session就会返回一对象; req对象中,添加了session对象。
    secret:"abc", 
    name: "userState",
    resave: false,   
    saveUninitialized: true,   
    cookie: {
        maxAge:1000*60*60   
    },
    rolling:false  //建议设置为false,以验证session失效。
}))

解析每一项的作用:

//配置中间件
app.use(session({
    secret: 'this is string key',   // 可以随便写。 一个 String 类型的字符串,作为服务器端生成 session 的签名
    name:'session_id',/*保存在本地cookie的一个名字 默认connect.sid  可以不设置*/
    resave: false,   /*强制保存 session 即使它并没有变化,。默认为 true。建议设置成 false。*/
    saveUninitialized: true,   //强制将未初始化的 session 存储。  默认值是true  建议设置成true
    //设置cookie在浏览器端
    cookie: {
        maxAge:1000*60    /*过期时间1min*/

    },   /*secure https这样的情况才可以访问cookie*/

    //设置过期时间比如是30分钟,只要游览页面,30分钟没有操作的话在过期

    rolling:true //在每次请求时强行设置 cookie,这将重置 cookie 过期时间(默认:false)
}))

设置404页面

// 处理404问题
app.all("*",function(req,res){
    // res.send('404页面')
    // 发送一个文件的内容给客户端
    res.sendFile(__dirname+"/public/404.html")
})

使用模板html

ejs和ajax跳转详情页

ajax

在a标签中先控制路由跳转,并动态传入当前点击的id:
在这里插入图片描述
然后在detail页面截取到location.href里面的id,ajax发起请求:
在这里插入图片描述
后台查询返回对应的数据,前端再由res渲染页面:
在这里插入图片描述

ejs

安装ejs

npm i ejs --save

创建views存放模板html
在这里插入图片描述
app.js中引入并配置:

const ejs = require('ejs')

//ejs的使用:
//设置模板视图的目录
app.set("views",__dirname + "/views");  //设置模板html为访问views文件夹

//设置是否启用视图编译缓存,启用将加快服务器执行效率
app.set("view cache",true);

// 2.注册html模板引擎:
app.engine('html',ejs.__express);

//设置模板引擎的格式即运用何种模板引擎
app.set("view engine","html");

设置动态路由goodsRouter.js:

使用req.params获取传入的id
给模板页面传数据:res.render(“views文件夹下的模板html名如:xxx.html”,{数据名1:数据值1,数据名2:数据值2})

const express = require("express")
const router = express.Router();
const db = require("./mysql")

module.exports = router;

// 动态路由  /goods/list/11, 利用路由中的URL传递参数: 

router.route("/list/:gid")
    .get((req, res) => {
        // 获取动态路由中的参数
        console.log(req.params);  //{ gid: '44' }
        let gid = req.params.gid;
        let sql = "select * from m_goods g,m_style  s where g.goods_style_id = s.style_id AND style_id= ?;"
        let param = [gid]
        db.query(sql, param)
            .then((data) => {
                console.log(data);
                res.render("city-man.html", {
                    bannerImg: "/img/" + data[0].style_banurl,
                    cnName: data[0].style_name,
                    enName: data[0].style_enName,
                    goods: data  // 对应一个数组
                }
                );
            })
            .catch((err) => {
                res.json({
                    status: 40001,
                    msg: '查询数据失败',
                    data: []
                })
            });
    })


在app.js引入goodsRouter.js并使用:
const goodsRouter = require("./routes/goodsRouter")
app.use('/goods',goodsRouter) //路由拦截

将模板页面数据改为模板数据:

页面中使用以下显示模板数据

  • 直接显示模板数据<%= 模板变量名 %>
  • 循环展示:
    <% for(let i = 0 ; i < 模板变量名.length; i++){ %>
    <%= 模板变量名[i].xxx %>
    <% }%>
案例:
views文件夹下的city-man.html
直接使用模板变量:
<img class="img-fluid" src="<%= bannerImg %>" alt="">

循环显示:
<div class="row justify-content-start">
				<% for(let i = 0 ; i < goods.length; i++){ %>
				<div class="col-3 mt-3 product-list-item">
					<div class="product-number"><%= goods[i].goods_num %></div>
					<div><img  class="product-img" src="/img/<%= goods[i].goods_slt %> " alt=""></div>
					<div class="product-link">
						<a href="/goodsdetails/<%= goods[i].goods_id %>" class="text-dark product-link-size">
							了解产品详情
							<br>
							<i class="fa fa-arrow-circle-o-right"></i>
						</a>
					</div>
				</div>
				<% }%>
			</div>

ejs模板+data数据=静态页面

ajax和ejs对比

在这里插入图片描述

文件上传

依赖于multer模块,router.js中处理:

const multer = require(“multer”) //1.引用文件中间件
const upload = multer({ dest: ‘uploads/’ });
//2. 会自动 基于项目根目录 (nodeJs)来创建uploads目录;
const fs = require(“fs”); //引用NODEjs自带的文件系统模块;

普通表单上传

html
<form name="userInfo1" action="/modifyUserInfo" method="POST" enctype="multipart/form-data">
  <div class="form-group row">
       <label for="usernick" class="col-lg-2 text-right col-form-label col-form-label-sm">昵称</label>
       <div class="col-lg-8">
           <input type="text" class="form-control " placeholder="用户昵称" value="张三" id="usernick" name="userName">
       </div>
   </div>
   <div class="form-group row">
       <label for="userPhoto" class="col-md-2 text-right col-form-label">用户头像</label>
       <div class="col-md-8">
           <input type="file" class="form-control" placeholder="请选择一个本地文件" id="userPhoto" name="userPhoto">
       </div>
   </div>
   <div class="form-group row">
       <label for="userbirthday" class="col-md-2 text-right col-form-label">出生日期</label>
       <div class="col-lg-8">
           <input type="datetime-local" name="birthday" class="form-control" id="userbirthday">
       </div>
   </div>
   <div class="form-group row">
       <div class="col-lg-2 text-right">性别</div>
       <div class="col-lg-8">
           <div class="form-check">
               <input class="form-check-input" type="radio" name="sex" id="sex1" value="" checked>
               <label class="form-check-label" for="sex1"></label>
           </div>
           <div class="form-check">
               <input class="form-check-input" type="radio" name="sex" id="sex2" value="" checked>
               <label class="form-check-label" for="sex2"></label>
           </div>
       </div>
   </div>
   <div class="form-group row">
       <label for="usertel" class="col-md-2 text-right col-form-label">电话</label>
       <div class="col-lg-8">
           <input type="tel" name="tel" class="form-control" id="usertel">
       </div>
   </div>
   <div class="form-group row">
       <label for="usermail" class="col-md-2 text-right col-form-label">电子邮箱</label>
       <div class="col-lg-8">
           <input type="email" name="email" class="form-control" id="usermail">
       </div>
   </div>
   <div class="form-group row">
       <div class="col-lg-4 offset-2 text-right">
           <button type="submit" class="btn btn-dark">提交</button>
       </div>
       <div class="col-lg-4">
           <button type="reset" class="btn btn-secondary">重置</button>
       </div>
   </div>
</form>

在这里插入图片描述
在这里插入图片描述

router.js
// 修改用户资料,
router.route("/modifyUserInfo")
    // single("参数名"),<input type= "file" name = "参数名" />
    .post(upload.single('userPhoto'), (req, res) => {
        // req.file=>接受上传的文件对象;
        // req.body => 其它表单域提交的数据;
        console.log(req.file)
        console.log(req.body);
        if (req.file != undefined) {
            let fileLastName = req.file.originalname.split(".")[1]; //获取原文件的扩展名 (.jpg)
            let oldFile = "uploads/"+req.file.filename;
            // let newFile = req.file.filename +"."+ fileLastName
            let newFile = 'public/fileUploads/' + new Date().getTime() + "." + fileLastName;

            fs.rename(oldFile, newFile, (err) => {
                if (err) {
                    throw err;
                } else {
                    // 组成新的文件路径 ,存储于Mysql中;
                    let pathName = newFile.replace("public/",'');
                    let { userName, birthday, sex, tel, email } = req.body;
                    // let u_id = req.session.user.id;
                    let u_id = 17;

                    let sql = `insert into m_userinfo value(?,?,?,?,?,?,?)`;
                    let param = [u_id,userName,tel,birthday,email,sex,pathName]
                    db.query(sql, param)
                    .then(data=>{
                        res.redirect("/html/myorder.html#userinfo")
                    })
                    .catch(err=>{
                        throw new Error("插入或修改失败")
                    })
                }
            })

        }
    })

ajax文件上传

htnl
<form name="userInfo2" >
   <div class="form-group row">
       <label for="usernick" class="col-lg-2 text-right col-form-label col-form-label-sm">昵称</label>
       <div class="col-lg-8">
           <input type="text" class="form-control " placeholder="用户昵称" value="张三" id="usernick" name="userName">
       </div>
   </div>
   <div class="form-group row">
       <label for="userPhoto" class="col-md-2 text-right col-form-label">用户头像</label>
       <div class="col-md-8">
           <input multiple type="file" class="form-control" placeholder="请选择一个本地文件" id="userPhoto" name="userPhoto">
       </div>
   </div>
   <div class="form-group row">
       <label for="userbirthday" class="col-md-2 text-right col-form-label">出生日期</label>
       <div class="col-lg-8">
           <input type="datetime-local" name="birthday" class="form-control" id="userbirthday">
       </div>
   </div>
   <div class="form-group row">
       <div class="col-lg-2 text-right">性别</div>
       <div class="col-lg-8">
           <div class="form-check">
               <input class="form-check-input" type="radio" name="sex" id="sex1" value="" checked>
               <label class="form-check-label" for="sex1"></label>
           </div>
           <div class="form-check">
               <input class="form-check-input" type="radio" name="sex" id="sex2" value="" checked>
               <label class="form-check-label" for="sex2"></label>
           </div>
       </div>
   </div>
   <div class="form-group row">
       <label for="usertel" class="col-md-2 text-right col-form-label">电话</label>
       <div class="col-lg-8">
           <input type="tel" name="tel" class="form-control" id="usertel">
       </div>
   </div>
   <div class="form-group row">
       <label for="usermail" class="col-md-2 text-right col-form-label">电子邮箱</label>
       <div class="col-lg-8">
           <input type="email" name="email" class="form-control" id="usermail">
       </div>
   </div>
   <div class="form-group row">
       <div class="col-lg-4 offset-2 text-right">
           <button type="button" class="btn btn-dark" id="modifyUserInfo">提交</button>
       </div>
       <div class="col-lg-4">
           <button type="reset" class="btn btn-secondary">重置</button>
       </div>
   </div>
</form>

在这里插入图片描述

router.js
// 修改用户资料,AJAX方式
router.route("/modifyUserInfoAjax")
    // single("参数名"),<input type= "file" name = "参数名" />
    .post(upload.single('userPhoto'), (req, res) => {
        // req.file=>接受上传的文件对象;
        // req.body => 其它表单域提交的数据;
        console.log(req.file)
        console.log(req.body);
        if (req.file != undefined) {
            let fileLastName = req.file.originalname.split(".")[1]; //获取原文件的扩展名 (.jpg)
            let oldFile = "uploads/"+req.file.filename;
            // let newFile = req.file.filename +"."+ fileLastName
            let newFile = 'public/fileUploads/' + new Date().getTime() + "." + fileLastName;

            fs.rename(oldFile, newFile, (err) => {
                if (err) {
                    throw err;
                } else {
                    // 组成新的文件路径 ,存储于Mysql中;
                    let pathName = newFile.replace("public/",'');
                    let { userName, birthday, sex, tel, email } = req.body;
                    // let u_id = req.session.user.id;
                    let u_id = 17;

                    let sql = `insert into m_userinfo value(?,?,?,?,?,?,?)`;
                    let param = [u_id,userName,tel,birthday,email,sex,pathName]
                    db.query(sql, param)
                    .then(data=>{
                       res.json({
                           status:200,
                           msg:"修改用户信息成功",
                           data:param
                       })
                    })
                    .catch(err=>{
                        res.json({
                            status:40001,
                            msg:"修改用户信息失败",
                            data:[]
                        })
                    })
                }
            })

        }
    })

AJAX请求,上传文件时,后端接口编码是multipart/form-data;前端使用 FormData对象来传参数 ;
把form的DOM对象放放new FormData()中,自动把表单域中所有值 ,都添加到new FormData()中。
FormData对象的数据,只能通过get()来获取 ;get()中放入表单域的name的值
console.log(formData); //FormData {},是不可见数据

  1. 原生的AJAX,formData时,不要请求头;
  2. $ajax时processData设置为false。因为data值是FormData对象,不需要对数据做处理。contentType设置为false。因为是由表单构造的FormData对象,且已经声明了属性enctype=“multipart/form-data”,所以这里设置为false。
    在这里插入图片描述
js文件

let modifyUserInfo = document.getElementById("modifyUserInfo");
const modifyUserInfoFn = () => {
    // AJAX请求,上传文件时,后端接口编码是multipart/form-data;
    // 前端使用 FormData对象来传参数 ;
    // 把form的DOM对象放放new FormData()中,自动把表单域中所有值 ,都添加到new FormData()中。 
    let formData = new FormData(document.getElementsByName("userInfo2")[0])
    // console.log(formData); //FormData {},是不可见数据
    // FormData对象的数据,只能通过get()来获取 ;get()中放入表单域的name的值 
    // console.log(formData.get("userName"));
    // console.log(formData.get("userPhoto"));

    // 1. 原生 的
       let xhr = new XMLHttpRequest();
       xhr.open("post","/modifyUserInfoAjax", true)
// 原生的AJAX,formData时,不要请求头;
       xhr.send(formData)
       xhr.onreadystatechange= ()=>{
           if(xhr.readyState === 4 && xhr.status === 200){
               let response = xhr.responseText;
               console.log(response);
           }
       }

// 2. $.ajax()
   $.ajax({
        url: "/modifyUserInfoAjax",
        type: 'POST',
        cache: false, //cache设置为false,上传文件不需要缓存。
        data: formData,
        processData: false, //processData设置为false。因为data值是FormData对象,不需要对数据做处理。
        contentType: false,  //contentType设置为false。因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。
        success: function (result) {
           if(result.status === 200){
            //    直接根据返回数据中的data,更新dom数据;
            //  或者  重新加载 当前页;
            location.reload(); //必须要保证页面有请求后台,获取用户信息数据;
           }
        },
        error: function (err) {
            console.log(err)
            alert(err.msg)
        }
    });

}

modifyUserInfo.onclick = modifyUserInfoFn;
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da Zeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值