[專案積累]後端專案之Koa2經驗整理

weixin_34138377發表於2019-01-13

1.0 koa配置跨域請求的解決方案

1.0.0 非模組解決方案
app.use(async function(ctx, next) {
  ctx.set("Access-Control-Allow-Origin", ctx.request.header.origin)
  ctx.set("Access-Control-Allow-Credentials", true);
  ctx.set("Access-Control-Max-Age", 86400000);
  ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE");
  ctx.set("Access-Control-Allow-Headers", "x-requested-with, accept, origin, content-type");
  await next()
})
1.0.1 外部模組匯入解決方案
// koa2跨域模組
const Cors = require("koa2-cors");
app.use(Cors({
  origin:function(ctx){
      console.log(ctx.url+"====koa");
      if(ctx.url==="/api"){
          return "*"//允許所有域名的請求
      }
      return "http://localhost:3000"//指定的請求域名+埠
  },
  exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],//表明伺服器支援的所有頭資訊字
  maxAge: 5,
  credentials: true,//表示是否允許傳送Cookie。預設情況下,Cookie不包括在CORS請求之中
  allowMethods: ['GET', 'POST', 'DELETE'], //設定允許的HTTP請求型別
  allowHeaders: ['Content-Type', 'Authorization', 'Accept'],//前端請求頭
}));

2.0 Axios 傳送請的時將json型別轉換成Form型別

6903052-fd3ba6cbab40ca78.jpg
axios在post請求的時候傳遞過去格式是json.jpg

上述問題造成koa解析後的資料格式不符合預料的形式

//ctx.req.on("data")時候的資料形式
{"uName":"是的規範的","uPwd":"sssssssssss"}
//字串序列化結果:
{ '{"uName":"是的規範的","uPwd":"ssssssssssss"}': 'undefined' }

import Qs from "qs"
//qs.parse()將URL解析成物件的形式
//qs.stringify()將物件 序列化成URL的形式,以&進行拼接
axios({
      transformRequest:[function(data){
     //在請求之前對data傳參進行格式轉換
     data = Qs.stringify(data);
     return data;
    }],
    method:"post",
    url:"/reg",
    headers:{
     "Content-type":"application/x-www-form-urlencoded;charset=utf-8"
      },
    data:{
         uName:this.uName.value,
        uPwd: this.uPwd.value
    }
 });

3.0 qs.stringify() 和JSON.stringify()的區別

var obj = {"name":"yxl","age":25};
qs.stringify(obj)//name=yxl&age=25
JSON.stringify(obj)//'{"name":"yxl","age":25}'

4.0 Koa2獲取post資料

4.0.1 原生Nodejs獲取Post資料
// 解析上下文裡node原生請求的POST引數
const parsePostData = (ctx,next)=>{
    return new Promise((resolve,reject)=>{
        try{
            let postData = "";
            // console.log(ctx);
            // 用原生的node req
            ctx.req.addListener("data",(chunk)=>{
                console.log(chunk)
                    postData+=chunk;
            });
            ctx.req.addListener("end",()=>{
                console.log(postData+"333");
                let parseData = parsePostQuery(postData);
                resolve(parseData);
            })
        }catch(err){
            reject(err);
        }
    });
}
//將POST請求引數字串解析成JSON
const parsePostQuery = (str)=>{
    let parse2JsonObj  = {};
    let queryStrArr = str.split("&");
    console.log(queryStrArr)
    // ["name=yyy","age=25","sex=nv"]
    // arr.entries()返回陣列的迭代物件[0,"str1"],[1,"str2"]
    for(let [index,queryString] of queryStrArr.entries()){
        let item  = queryString.split("=");
        parse2JsonObj[item[0]] = decodeURIComponent(item[1]);
    }
    return parse2JsonObj;
}
let Utils = {
    parsePostData,
    parsePostQuery
}
module.exports = Utils;
4.0.1 koa-body模組解決post請求
//home.ejs<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <h1><%=title%></h1>
    <form action="http://localhost:3002/multipleFile" method="post" enctype="multipart/form-data">
    多檔案 <input type="file" name="file" id="file" value="" multiple="multiple" />
    <input type="submit" value="提交"/>
</form>
<hr>
<form action="http://localhost:3002/singleFile" method="post"  enctype="multipart/form-data">
    單檔案 <input type="file" name="file2" id="file2" value=""  />
    <input type="submit" value="提交"/>
</form> 
<hr>
<form action="http://localhost:3002/textField" method="post" enctype="application/x-www-form-urlencoded">
   使用者名稱 <input type="text" name="username"/>
    密碼<input type="password"  name="pwd"/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>
const Koa = require("koa");
const router = require("koa-router")();
// const bodyParse = require("koa-bodyParse");
const KoaBody = require("koa-body");
const views = require("koa-views");
const path = require("path");
const fs = require("fs");

const app = new Koa();
const tempPath = path.resolve(__dirname,"./views");
app.use(KoaBody({
    multipart:true,
    formidable: {
        maxFileSize: 200*1024*1024    // 設定上傳檔案大小最大限制,預設2M
    }
}));
app.use(views(path.resolve(__dirname,"./views"),{
    extension:"ejs"
}));
router.get("/",async (ctx,next)=>{
    let  title ="檔案上傳測試";
    await ctx.render("home",{title})
});
router.post("/singleFile",async (ctx,next)=>{
    console.log(ctx.request);
    let file = ctx.request.files.file2;
    console.log(file);
    // console.log(file);
    // 建立檔案可讀流
    let reader = fs.createReadStream(file.path);

    // 建立上傳檔案的存放位置
    let uploadPath = path.join(__dirname,"public/upload/")+`${file.name}`;
    // // 建立檔案可寫流
    // console.log(uploadPath);
    let write = fs.createWriteStream(uploadPath);
    // // 通過管道輸出
    reader.pipe(write);
    await next();
    return ctx.body = "單個檔案上傳成功";
});
router.post("/multipleFile",async (ctx,next)=>{
    console.log(ctx.request.files);
    let files = ctx.request.files.file;
    for(let file of files){
        // 建立檔案可讀流
        let reader = fs.createReadStream(file.path);
        // 建立上傳檔案的存放位置
        let uploadPath = path.join(__dirname,"public/upload/")+`${file.name}`;
        // 建立檔案可寫流
        let write = fs.createWriteStream(uploadPath);
        // 通過管道輸出
        reader.pipe(write);
        await next();
    }
    return ctx.body = "多個檔案上傳成功";
});
router.post("/textField",async(ctx ,next)=>{
        // console.log(ctx.request)
        ctx.body = JSON.stringify(ctx.request.body);
        console.log(ctx.request.body);
        await next();
});
app.use(router.routes());
app.listen("3002",()=>{
    console.log("監聽這3002埠")
})

相關文章