node实现自动化图片切割压缩, 部署页面

图片切割部分参考:https://www.cnblogs.com/gating/p/12488443.html

  其他方法: https://www.jianshu.com/p/8c08a6b23054
       https://www.cnblogs.com/zycbloger/p/6230155.html
  

文件结构部分

  imgclip
    images   ---图片切割后的存放目录
    img         ---源图片文件夹
    node_modules  --依赖包
    static    ---存放静态html文件

      index.html
    app.js   ---静态伺服启动文件
    clip_config.js   ---切割配置
    clip_images.js  ---切割图片模块
    package.json  

 

 

实现图片切割过程:

切割图片主要依赖   canvas库

const {
    createCanvas,
    loadImage
} = require("canvas");

 

将图片用cavas转为画板 , 然后再讲画板切割出来 , 再然后将切割出来的画板 , 转为图片

 

压缩图片过程

压缩图片主要依赖   canvas库

var images = require("images");

cavas模块, images模块 , npm下载不顺的话 , 可以尝试yarn 和 cnpm


渲染页面
  主要依赖app.js 配置静态伺服
  指定端口和静态文件目录 , 监听路由
  检测文件, 判断文件, 处理文件
  动态渲染dom结构


index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Document</title>
    <style>
        body {
            width: 960px;
            margin: 0px auto;
        }

        html,
        body {
            margin: 0px;
            padding: 0;
        }

        .cell {
            float: left;
            margin: 10px;
            position: relative;
            width: 200px;
            height: 230px;
            cursor: pointer;
        }

        .cell span,
        .cell img {
            position: absolute;
        }

        .cell img {
            width: 200px;
            height: 200px;
            top: 0;
        }

        .cell span {
            width: 200px;
            height: 30px;
            line-height: 30px;
            top: 200px;
            left: 0px;
            text-align: center;
            font-size: 18px;
        }

        img {
            display: block;
        }

        img {
            display: block;
            border: 0;
        }

        .warp {
            width: 100%;
            overflow: hidden;
        }

        .warp img {
            position: relative;
            top: 0;
            left: 50%;
            transform: translateX(-50%);
        }
    </style>
</head>

<body>
    <div class="warp">

 

app.js

// 引入内置模块
var http = require('http');
var fs = require('fs');
var url = require('url');
var path = require('path');
var querystring = require('querystring');
const {
    resolve
} = require('path');
//导入配置
const {
    entry,
    output,
    imgPrefix,
    imgUrl
} = require('./clip_config.js');
// 配置路径
const entryPath = __dirname + "/" + entry
const outputPath = __dirname + "/" + output

// 引入自定义模块
var clip_images = require('./clip_images.js');

// 创建端口
var port = 3000;
// 创建服务
var server = http.createServer();

console.log(imgUrl)
// 监听服务
server.on("request", function (req, res) {
    if (req.url !== "/favicon.ico") {
        var urlObj = url.parse(req.url, true);
        var pathname = urlObj.pathname;
        if (pathname == "/" && req.method == "GET") {
            resHead(".html")
            res.end("<h1>请进入images目录</h1>");
            return;
        }
        if (pathname == "/images" && req.method == "GET") {
            let saveImageName = ''; //原名
            let currentImageName = '';
            fs.readdir(entryPath, function (err, files) {
                if (files.length) {
                    files.forEach((file, index) => {
                        saveImageName = entryPath + "/" + file;
                        currentImageName = entryPath + "/aaa" + getExtname(file);
                        fs.rename(saveImageName, currentImageName, (err) => {
                            if (err) throw err;
                            clip_images("aaa" + getExtname(file))
                            fs.rename(currentImageName, saveImageName, (err) => {
                                if (err) throw err;
                            })
                        })
                    })
                } else {
                    throw err;
                }
            })

            if (isDir(outputPath)) {
                rDir(outputPath);
            } else {

            }

            //配置静态图片
        } else if (pathname == "/static/img/file.jpg" && req.method == "GET") {
            fs.readFile("./static/img/file.jpg", function (err, data) {
                resHead(".jpg");
                res.end(data);
            })
        } else if (pathname == "/static/img/css.jpg" && req.method == "GET") {
            fs.readFile("./static/img/css.jpg", function (err, data) {
                resHead(".jpg");
                res.end(data);
            })
        } else if (pathname == "/static/img/html.jpg" && req.method == "GET") {
            fs.readFile("./static/img/html.jpg", function (err, data) {
                resHead(".jpg");
                res.end(data);
            })
        } else if (pathname == "/static/img/js.jpg" && req.method == "GET") {
            fs.readFile("./static/img/js.jpg", function (err, data) {
                resHead(".jpg");
                res.end(data);
            })
        } else if (pathname == "/static/img/json.jpg" && req.method == "GET") {
            fs.readFile("./static/img/json.jpg", function (err, data) {
                resHead(".jpg");
                res.end(data);
            })
        } else if (pathname == "/static/img/txt.jpg" && req.method == "GET") {
            fs.readFile("./static/img/txt.jpg", function (err, data) {
                resHead(".jpg");
                res.end(data);
            })
        }
        fs.readFile("." + pathname, function (err, data) {
            fs.stat("." + pathname, function (err, stats) {
                if (err) {
                    resHead(".html");
                    res.end("<h1>No file or No dir");
                    return;
                }
                if (stats.isDirectory()) {
                    rDir("." + pathname)
                } else {
                    var mine = getExtname(pathname);
                    resHead(mine);
                    res.end(data)
                }
            })
        });

        function isDir(p) { //判断是否是文件夹,如果是文件夹返回true,如果不是返回false
            var stats = fs.statSync(p);
            var flag = stats.isDirectory();
            return flag;
        }

        function rFile(p) { //如果不是文件夹,读取对应的文件,并展示
            fs.readFile(p, "utf8", function (err, data) {
                var mine = getExtname(pathname);
                resHead(mine);
                res.end(data);
            })
        }

        function compareFiles(a, b) {
            console.log(a, b)
            return 1
        }

        function rDir(p) { //如果是文件夹,读取对应的文件夹,并展示
            var str = "";
            fs.readdir(p, function (err, files) {
                if (files.length) { //files获取出来的
                    var data = fs.readFileSync("./static/index.html", "utf8");
                    str += data;
                    //排序
                    var lastNumRes = /\d{1,3}\.(png|jpg|gif|jpeg|webp)$/g;
                    var filesArr = [];
                    files.forEach((file, i) => {
                        filesArr[i] = file.replace(lastNumRes, (i + 1) + getExtname(file));
                    })
                    //渲染
                    for (var i = 0; i < filesArr.length; i++) {
                        var extname = getExtname(filesArr[i]); //后缀
                        str += setHtml(extname, filesArr[i], req.url); //渲染函数
                    }
                    str += `
                        <script>
                            function fun(a,b){
                                window.location.href = a + "/" + b;
                            }
                        </script>
                        </body></html>`;
                    resHead(".html");
                    res.end(str);
                } else {
                    resHead(".html");
                    str += "<h1>This folder has no content</h1>";
                    res.end(str);
                }
            })
        }

        function getExtname(p) { //获取文件的后缀名
            var ext = path.extname(p);
            return ext;
        }

        function setHtml(extname, p, q) { //渲染HTML模板
            var extname = extname.slice(1)
            if (extname == "html") {
                return `<div class="cell" onclick=fun('${req.url}','${p}')>
                    <img src="/static/img/${extname}.jpg" alt="">
                    <span>${p}</span>
                </div>`
            } else if (extname == "css") {
                return `<div class="cell" onclick=fun('${req.url}','${p}')>
                    <img src="/static/img/${extname}.jpg" alt="">
                    <span>${p}</span>
                </div>`
            } else if (extname == "js") {
                return `<div class="cell" onclick=fun('${req.url}','${p}')>
                    <img src="/static/img/${extname}.jpg" alt="">
                    <span>${p}</span>
                </div>`
            } else if (extname == "json") {
                return `<div class="cell" onclick=fun('${req.url}','${p}')>
                    <img src="/static/img/${extname}.jpg" alt="">
                    <span>${p}</span>
                </div>`
            } else if (extname == "txt") {
                return `<div class="cell" onclick=fun('${req.url}','${p}')>
                    <img src="/static/img/${extname}.jpg" alt="">
                    <span>${p}</span>
                </div>`
            } else if (extname == "png") {
                return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
            } else if (extname == "jpg") {
                return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
            } else if (extname == ".jpeg") {
                return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
            } else if (extname == ".png") {
                return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
            } else if (extname == "") {
                return `<div class="cell" onclick=fun('${req.url}','${p}')>
                    <img src="/static/img/file.jpg" alt="">
                    <span>${p}</span>
                </div>`
            } else {
                return `<h1>不支持该文件类型</h1>`
            }
        }

        function resHead(p) { //根据文件类型设置请求头
            if (p == "") {
                return res.writeHead(200, {
                    'Content-Type': 'image/jpg'
                });
            } else if (p == ".css") {
                return res.writeHead(200, {
                    'Content-Type': 'text/css; charset=utf-8'
                });
            } else if (p == ".js") {
                return res.writeHead(200, {
                    'Content-Type': 'text/javascript; charset=utf-8'
                });
            } else if (p == ".html") {
                return res.writeHead(200, {
                    'Content-Type': 'text/html; charset=utf-8'
                });
            } else if (p == ".json") {
                return res.writeHead(200, {
                    'Content-Type': 'text/json; charset=utf-8'
                });
            } else if (p == ".txt") {
                return res.writeHead(200, {
                    'Content-Type': 'text/plain; charset=utf-8'
                });
            } else if (p == ".png") {
                return res.writeHead(200, {
                    'Content-Type': 'image/png'
                });
            } else if (p == ".jpg") {
                return res.writeHead(200, {
                    'Content-Type': 'image/jpg'
                });
            } else if (p == ".jpeg") {
                return res.writeHead(200, {
                    'Content-Type': 'image/jpg'
                });
            } else if (p == ".gif") {
                return res.writeHead(200, {
                    'Content-Type': 'image/gif'
                });
            }
        }
    }
})

// 监听端口
server.listen(port);
console.log("server running in 127.0.0.1:" + port);

 

clip_images.js

// 创建写入流
const {
    createWriteStream
} = require("fs");
const fs = require('fs');
const path = require('path')
var images = require("images");
// 导入canvas库,用于裁剪图片
const {
    createCanvas,
    loadImage
} = require("canvas");
//导入配置
let {
    entry,
    output,
    imgPrefix,
    imgHeight
} = require('./clip_config.js');

// 配置路径
const entryPath = __dirname + "/" + entry
const outputPath = __dirname + "/" + output



module.exports = async function clip_images(imgName) {
    //删除输出路径下的所有文件
    function deleteFolder(path) {
        let files = [];
        if (fs.existsSync(path)) {
            files = fs.readdirSync(path);
            files.forEach(function (file, index) {
                let curPath = path + "/" + file;
                if (fs.statSync(curPath).isDirectory()) {
                    deleteFolder(curPath);
                } else {
                    fs.unlinkSync(curPath);
                }
            });
            //  fs.rmdirSync(path);
        }
    }
    deleteFolder(outputPath)
    // 加载图片
    const image = await loadImage(entryPath + '/' + imgName);
    // 获取图片宽高
    const {
        width,
        height
    } = image;
    // 创建等宽登高的canvas
    const mainCanvas = createCanvas(width, height);
    // 获取canvas上下文
    const ctx = mainCanvas.getContext("2d");
    // 绘图
    ctx.drawImage(image, 0, 0);
    // oneHeight 获取一份的高度,   canvasX: canvas中的 X , 从哪里开始画
    let canvasX, oneHeight;
    canvasX = oneHeight = imgHeight;
    // 明确我们需要垂直分割成几份
    const num = (height / oneHeight) > Math.floor(height / oneHeight) ? //总张数
        Math.floor(height / oneHeight) + 1 : height / oneHeight;
    const lastHeight = (1 + (height / oneHeight - num)) * oneHeight; //最后一张的高度
    let imgUrl = '';

    for (let i = 0; i < num; i++) {
        if (i == (num - 1)) {
            oneHeight = lastHeight;
        }
        // 创建一份裁剪的canvas
        let clipCanvas = createCanvas(width, oneHeight);
        // 获取canvas上下文
        const clipCtx = clipCanvas.getContext("2d");
        // 通过 clipCtx 裁剪 mainCanvas
        clipCtx.drawImage(
            mainCanvas,
            0,
            canvasX * i,
            width,
            oneHeight,
            0,
            0,
            width,
            oneHeight
        );

        imgUrl = outputPath + `/${imgPrefix+(i + 1)}` + path.extname(imgName);
        fs.writeFileSync(imgUrl, clipCanvas.toBuffer(), 'binary', function (err) {

        })
        images(imgUrl)
            .save(imgUrl, {
                quality: 95 //保存图片到文件,图片质量为50
            });
        // 主动释放内存
        clipCanvas = null;
    }
};

 

clip_config.js

const ConfigObj = {
    imgHeight: 350, //裁剪图片的高度
    entry: "img", //输入路径
    output: "images", //输出路径
    imgPrefix: "aaa_", //输出图片名前缀
    // imgUrl: "https://img.hbhcdn.com/zhuanti/20841"  //配置图片src
}

module.exports = ConfigObj;

 

package.json

 

archiver   压缩文件库
canvas库,用于裁剪图片

compressing  压缩与解压

images  图片处理

unzip  解压zip

bcryptjs 加密

 

{
  "name": "clip",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "archiver": "^5.2.0",
    "bcryptjs": "^2.4.3",
    "canvas": "^2.6.1",
    "compressing": "^1.5.1",
    "images": "^3.2.3",
    "unzip": "^0.1.11"
  }
}

 ...

 

 

  

posted @ 2021-01-22 15:48  混名汪小星  阅读(276)  评论(0编辑  收藏  举报