zoukankan      html  css  js  c++  java
  • koa 快速保存文件的服务器

    import * as Koa from "koa";
    import * as fs from "fs";
    import * as path from "path";
    
    
    const app = new Koa();
    
    app.use(async ctx => {
        // console.log(ctx.url);
        // console.log(ctx.method);
        // let postData = await parsePostData(ctx);
        // ctx.body = 'Hello World';
        if (isPost("/", ctx)) {
            let postData = await parsePostData(ctx);
            console.log("收到的参数postData: ", postData);
            saveFile(JSON.stringify(postData));
        }
    });
    
    //设置监听端口
    app.listen(3000, () => {
        console.log("服务器开启 127.0.0.1:3000");
    });
    
    let saveFilePath = "./File";
    let saveFileName = "tongguanTime.json";
    
    /** 保存文件 
     * @param content 保存的文件内容
    */
    function saveFile(content: string) {
    
        if (!fs.existsSync(saveFilePath)) {
            if (mkdirsSync(saveFilePath)) {
                console.log(`${saveFilePath} 创建成功`);
            }
        }
    
        try {
            fs.writeFileSync(path.join(saveFilePath, saveFileName), content);
            console.log("文件保存成功");
        } catch (error) {
            console.log(error);
        }
    
    }
    
    /** 递归创建文件夹 
     * @param dirPath 文件夹路径
    */
    function mkdirsSync(dirPath) {
        if (fs.existsSync(dirPath)) {
            return true;
        } else {
            if (mkdirsSync(path.dirname(dirPath))) {
                fs.mkdirSync(dirPath);
                return true;
            }
        }
    }
    
    
    /** 解析 post 参数 */
    function parsePostData(ctx) {
        return new Promise((resolve, reject) => {
            try {
                let postData = '';
                ctx.req.addListener('data', (data) => { // 有数据传入的时候
                    postData += data;
                });
                ctx.req.on('end', () => {
                    let parseData = parseQueryStr(postData);
                    resolve(parseData);
                });
            } catch (e) {
                reject(e);
            }
        })
    }
    
    // 处理 string => json
    function parseQueryStr(queryStr) {
        // console.log("queryStr: ",queryStr);
        let queryData = {};
        let queryStrList = queryStr.split('&');
        // console.log("queryStrList: ",queryStrList);
        for (let queryStr of queryStrList) {
            let itemList = queryStr.split('=');
            // console.log('itemList: ', itemList);
            queryData[itemList[0]] = decodeURIComponent(itemList[1]);
        }
        // console.log("queryData: ",queryData);
        return queryData;
    }
    
    /** 是否是post请求
     * @param path url路径
     * @param ctx koa2的上下文对象
     */
    function isPost(path, ctx) {
        return ctx.url === path && ctx.method === 'POST';
    }

    主要是今天老总让我玩游戏,然后把游戏中的通关时间记录一下,但是egret不能保存文件。所以写了这个服务器用来保存文件。

    egret的游戏每次通了一关,就向这个服务器发起请求,然后再把数据保存成文件。

    把代码记录在博客,方便下次我复制。

    使用postman 测试OK。

    最后,再添加一些 安全的保存文件方法:

    index.ts

    import * as Koa from "koa";
    import * as fs from "fs";
    import * as path from "path";
    
    const app = new Koa();
    
    app.use(async ctx => {
        //解决 egret 请求时,跨域的问题
        ctx.set('Access-Control-Allow-Origin', '*');
    
    
        if (isPost("/", ctx)) {
            let postData = await parsePostData(ctx);
            // console.log("收到的参数postData: ", postData);
            safeSaveFile(JSON.stringify(postData));
    
            //一定要返回一个响应,不然egret那边会报 Uncaught Error: #1011: 流错误。
            ctx.body = "文件保存成功";
        }
    });
    
    //设置监听端口
    app.listen(3000, () => {
        console.log("服务器开启 127.0.0.1:3000");
    });
    
    /** 保存的目录 */
    let saveDirPath = "./File";
    /** 保存的文件名 */
    let saveFileName = "tongguanTime.json";
    /** 保存的文件路径 */
    let saveFilePath = path.join(saveDirPath, saveFileName);
    
    /** 保存文件 
     * @param content 保存的文件内容
    */
    function saveFile(content: string) {
    
        if (!fs.existsSync(saveDirPath)) {
            if (mkdirsSync(saveDirPath)) {
                console.log(`${saveDirPath} 创建成功`);
            }
        }
    
        try {
            fs.writeFileSync(saveFilePath, content);
            console.log("文件保存成功");
        } catch (error) {
            console.log(error);
        }
    
    }
    
    /** 安全的保存文件 如果已经存在该文件,则读取该文件的内容,然后将要保存的内容,已有的覆盖,没有的追加。如果该文件的内容不合规,则复制一份暂时保存
     * @param saveJsonStr 保存的文件内容
    */
    function safeSaveFile(saveJsonStr: string) {
        let fileJsonObj = {};
        if (fs.existsSync(saveFilePath)) {
            let fileJsonStr = fs.readFileSync(saveFilePath).toString();
            try {
                fileJsonObj = JSON.parse(fileJsonStr);
            } catch (error) {
                console.log("不是json格式的内容,已重置");
                fs.copyFileSync(saveFilePath, path.join(saveDirPath, Date.now() + "_" + saveFileName))
                fileJsonObj = {};
            }
    
        }
    
        /** 要保存的json对象 */
        let saveJsonObj = JSON.parse(saveJsonStr);
    
        if (isNullObj(fileJsonObj)) {
            // console.log("是个空对象");
            fileJsonObj = saveJsonObj;
        } else {
            for (const key in saveJsonObj) {
                if (saveJsonObj.hasOwnProperty(key)) {
    
                    //如果已存在的文件中,和要保存的json对象 内容一致,则记录老的值,并将新的值添加
                    // if (fileJsonObj[key] != element) {
                    //     fileJsonObj[key + "_old"] = fileJsonObj[key];
                    // }
                    fileJsonObj[key] = saveJsonObj[key];
                }
            }
        }
        //写入文件
        try {
            fs.writeFileSync(saveFilePath, JSON.stringify(fileJsonObj));
            console.log("保存的内容:", fileJsonObj);
            console.log("文件保存成功");
        } catch (error) {
            console.log(error);
        }
    
    }
    
    /** 判断是否是空对象 */
    function isNullObj(obj) {
    
        for (var key in obj) {
            return false;
        }
        return true;
    
    }
    
    /** 递归创建文件夹 
     * @param dirPath 文件夹路径
    */
    function mkdirsSync(dirPath) {
        if (fs.existsSync(dirPath)) {
            return true;
        } else {
            if (mkdirsSync(path.dirname(dirPath))) {
                fs.mkdirSync(dirPath);
                return true;
            }
        }
    }
    
    
    /** 解析 post 参数 */
    function parsePostData(ctx) {
        return new Promise((resolve, reject) => {
            try {
                let postData = '';
                ctx.req.addListener('data', (data) => { // 有数据传入的时候
                    postData += data;
                });
                ctx.req.on('end', () => {
                    let parseData = parseQueryStr(postData);
                    resolve(parseData);
                });
            } catch (e) {
                reject(e);
            }
        })
    }
    
    // 处理 string => json
    function parseQueryStr(queryStr) {
        // console.log("queryStr: ",queryStr);
        let queryData = {};
        let queryStrList = queryStr.split('&');
        // console.log("queryStrList: ",queryStrList);
        for (let queryStr of queryStrList) {
            let itemList = queryStr.split('=');
            // console.log('itemList: ', itemList);
            queryData[itemList[0]] = decodeURIComponent(itemList[1]);
        }
        // console.log("queryData: ",queryData);
        return queryData;
    }
    
    /** 是否是post请求
     * @param path url路径
     * @param ctx koa2的上下文对象
     */
    function isPost(path, ctx) {
        return ctx.url === path && ctx.method === 'POST';
    }

     这是egret的客户端代码:

    HttpRequestUtil.ts

    /** http请求测试用 */
    class HttpRequestUtil {
    
        /** 保存通关记录到服务器 */
        static saveTongGuanTime(jsonStr: string) {
            let url = "http://127.0.0.1:3000";
            this.startPost(url, jsonStr);
        }
    
        /** 开始post请求 */
        static startPost(url: string, json: string) {
    
    
            //new http请求
            const request = new egret.HttpRequest();
            // request.responseType = egret.HttpResponseType.TEXT;
            //请求参数
            // var params = "p1=postP1&p2=postP2";
    
            //发送post请求
            request.open(url, egret.HttpMethod.POST);
    
            //设置响应头
            // request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
            // request.setRequestHeader("Content-Type", "application/json;charset=utf-8");
    
            //发送参数
            request.send(this.jsonToPostParmameter(json));
    
            //监听当前请求完成后,返回数据
            request.addEventListener(egret.Event.COMPLETE, function (evt) {
                //请求返回数据
                var data = request.response;
                console.log("收到的数据: ", data);
            }, this);
        }
    
        /** json -> post 参数格式 
         * @param jsonStr json字符串
        */
        static jsonToPostParmameter(jsonStr: string) {
            let postParmStr = "";
            let jsonObj = JSON.parse(jsonStr);
            for (let key in jsonObj) {
                if (jsonObj.hasOwnProperty(key)) {
                    let element = jsonObj[key];
                    postParmStr += `${key}=${element}&`;
                }
            }
            postParmStr = postParmStr.substring(0, postParmStr.lastIndexOf('&'));
            return postParmStr;
        }
    }
  • 相关阅读:
    Python 列表浅拷贝与深拷贝
    Linux 基本命令-----常用操作分类
    硬盘的分区方式
    github中fork的使用
    大O记号
    python的__file__和__name__变量
    python生成器
    python装饰器
    re模块元字符
    python_数据类型_list
  • 原文地址:https://www.cnblogs.com/dmc-nero/p/13094222.html
Copyright © 2011-2022 走看看