圖片壓縮 借用了images、imagemin等第三方庫,壓縮jpg、Png圖片 viteImagemin也可以實現,代碼量更加少,squoosh就沒用過了 輸入需要壓縮的文件 //判斷是否已經有這個文件路徑 function setInputName() { return new Promise( ...
圖片壓縮
借用了images、imagemin等第三方庫,壓縮jpg、Png圖片
viteImagemin也可以實現,代碼量更加少,squoosh就沒用過了
輸入需要壓縮的文件
//判斷是否已經有這個文件路徑
function setInputName() {
return new Promise((resolve, reject) => {
inputVlaue.question('請輸入需要壓縮文件夾名稱:', async (val) => {
let asr = val.replace(/\s+/g, "");
if (asr == 'imagesTest') {
console.log("不可以與預設輸出文件夾重名");
return setFileName("請重新輸入!\n")
} else if (!reg.test(asr)) {
console.log("只能輸入英文");
return setFileName("請重新輸入!\n")
}
positionDir = path.join(process.cwd(), asr)
console.log(positionDir);
resolve(positionDir)
})
})
}
不存在則自動創建文件
不建議在調用 fs.open() 、fs.readFile() 或 fs.writeFile() 之前使用 fs.stat() 檢查一個文件是否存在。 作為替代,用戶代碼應該直接打開/讀取/寫入文件,當文件無效時再處理錯誤。
如果要檢查一個文件是否存在且不操作它,推薦使用 fs.access()
這裡使用node內置path處理文件
function createTimeFile(positionDir) {
let time_PATH = path.resolve(__dirname, positionDir);//獲取是否已經存在這個文件
return new Promise((resolve, reject) => {
fs.stat(time_PATH, (err, stat) => {
if (err) {
fs.mkdir(positionDir, { recursive: true }, (err) => {
resolve(err)
console.log(`創建${positionDir}成功!`);
})
} else {
resolve(stat)
}
})
})
}
文件創建成功,輸入xx指令進行壓縮
function ready() {
let msg=`請把所需壓縮圖片放入${positionDir}輸入yes,開始壓縮圖片!\n`
inputVlaue.question(msg, answers => {
let asr = answers.trim().toLocaleLowerCase()
if (asr == "yes") {
console.log("開始壓縮...\n");
setImageData()
} else {
ready("指令錯誤請重新輸入,輸入yes開始壓縮圖片\n")
}
})
}
讀取需要壓縮的文件
//讀取需要壓縮的文件夾
function getReadFile() {
fs.readdir(positionDir, "utf-8", (err, data) => {
console.log(data.length);
if (data.length == 0) {
console.log("還沒有圖片,請添加");
}
data.forEach((item, index) => {
let filePath = path.join(positionDir, item)
let filename = filePath.replace(/\\/g, "/");//把 \ 替換為 /
let output = filename.replace(positionDir.replace(/\\/g, "/"), outputDir.replace(/\\/g, "/"));//輸出位置
if (path.extname(item) == ".png") {
pngArrayList.push({ filename, output })
} else if (path.extname(item) == ".jpg") {
jpgArrayList.push({ filename, output })
} else if (fs.statSync(filePath).isDirectory()) {
readfile(filePath)
}
})
})
}
針對jpg和png處理使用不同的方法
function setImageData() {
if (jpgArrayList.length != 0) {
jpgArrayList = rmSame(jpgArrayList)
//壓縮jpg
console.log(jpgArrayList);
jpgArrayList.forEach(item => {
createTimeFile(path.dirname(item.output))
images(item.filename).save(item.output, { quality: 60 })
})
}
//壓縮png
pngArrayList = rmSame(pngArrayList)
pngCompress(pngArrayList, pngArrayList.length - 1)
}
function rmSame(arr) {
let newArray = []
let arrObj = []
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
if (newArray.indexOf(element['filename']) == -1 && (fs.statSync(element['filename']).size > 1024)) {
newArray.push(element['filename'])
arrObj.push(element)
} else if (newArray.indexOf(element['filename']) == -1 && (fs.statSync(element['filename']).size <= 1024)) {
let pathDir = path.dirname(element['output'])
createTimeFile(pathDir)//判斷存放壓縮的文件夾是否已經存在,不存在則創建
fs.createReadStream(element['filename']).pipe(fs.createWriteStream(element['output']))
console.log(`圖片${element['filename']}記憶體過小,直接轉移到${element['output']}`)
}
}
return arrObj
}
//png壓縮圖片
function pngCompress(arr, index) {
//壓縮結束
if (index < 0) {
console.log("\n本視窗在5秒後關閉!")
setTimeout(() => {
inputVlaue.close()
}, 5000)
return
}
let pathDir = path.dirname(arr[index]['output'])
let filename = arr[index]['filename']
createTimeFile(pathDir)
imagemin([filename], {
destination: pathDir,
plugins: [
imageminPngquant({
quality: [0.6, 0.7]
})
]
}).then(() => {
console.log(`圖片${filename}壓縮完成!`);
pngCompress(arr, index - 1)
}).catch(err => {
console.log(`${arr[index]['filename']}圖片壓縮不了了,直接轉移到${arr[index]['output']}`)
fs.createReadStream(arr[index]['filename']).pipe(fs.createWriteStream(arr[index]['output']))
pngCompress(arr, index - 1)
});
}
全部代碼
/*
* @Author: zlc
* @Date: 2022-04-14 16:34:12
* @LastEditTime: 2022-04-15 10:26:16
* @LastEditors: zlc
* @Description: 圖片壓縮
* @FilePath: \git項目\project-template\案例\圖片壓縮\imagemin\src\app.js
*/
const fs = require("fs")
const imagemin = require('imagemin');
const imageminPngquant = require('imagemin-pngquant');
const path = require("path")
const images = require("images")
const readline = require("readline");
const { resolve } = require("path");
const inputVlaue = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let outputDir = path.join(process.cwd(), "imagesTest")
let reg = /^[a-zA-Z]+$/
let positionDir, timeId, pngArrayList = [], jpgArrayList = []
let timeIndex = 0
const setCompress = async () => {
await setInputName();//輸入內容
await createTimeFile(positionDir);//創建文件
await getReadFile()//讀取文件
ready()//開始壓縮
}
//判斷是否已經有這個文件路徑
function setInputName() {
return new Promise((resolve, reject) => {
inputVlaue.question('請輸入需要壓縮文件夾名稱:', async (val) => {
let asr = val.replace(/\s+/g, "");
if (asr == 'imagesTest') {
console.log("不可以與預設輸出文件夾重名");
return setFileName("請重新輸入!\n")
} else if (!reg.test(asr)) {
console.log("只能輸入英文");
return setFileName("請重新輸入!\n")
}
positionDir = path.join(process.cwd(), asr)
console.log(positionDir);
resolve(positionDir)
})
})
}
//創建圖片文件
function createTimeFile(positionDir) {
let time_PATH = path.resolve(__dirname, positionDir);//獲取是否已經存在這個文件
return new Promise((resolve, reject) => {
fs.stat(time_PATH, (err, stat) => {
if (err) {
fs.mkdir(positionDir, { recursive: true }, (err) => {
resolve(err)
console.log(`創建${positionDir}成功!`);
})
} else {
resolve(stat)
}
})
})
}
//讀取需要壓縮的文件夾
function getReadFile() {
fs.readdir(positionDir, "utf-8", (err, data) => {
console.log(data.length);
if (data.length == 0) {
console.log("還沒有圖片,請添加");
}
data.forEach((item, index) => {
let filePath = path.join(positionDir, item)
let filename = filePath.replace(/\\/g, "/");//把 \ 替換為 /
let output = filename.replace(positionDir.replace(/\\/g, "/"), outputDir.replace(/\\/g, "/"));//輸出位置
if (path.extname(item) == ".png") {
pngArrayList.push({ filename, output })
} else if (path.extname(item) == ".jpg") {
jpgArrayList.push({ filename, output })
} else if (fs.statSync(filePath).isDirectory()) {
readfile(filePath)
}
})
})
}
function ready() {
let msg=`請把所需壓縮圖片放入${positionDir}輸入yes,開始壓縮圖片!\n`
inputVlaue.question(msg, answers => {
let asr = answers.trim().toLocaleLowerCase()
if (asr == "yes") {
console.log("開始壓縮...\n");
setImageData()
} else {
ready("指令錯誤請重新輸入,輸入yes開始壓縮圖片\n")
}
})
}
function setImageData() {
if (jpgArrayList.length != 0) {
jpgArrayList = rmSame(jpgArrayList)
//壓縮jpg
console.log(jpgArrayList);
jpgArrayList.forEach(item => {
createTimeFile(path.dirname(item.output))
images(item.filename).save(item.output, { quality: 60 })
})
}
//壓縮png
pngArrayList = rmSame(pngArrayList)
pngCompress(pngArrayList, pngArrayList.length - 1)
}
function rmSame(arr) {
let newArray = []
let arrObj = []
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
if (newArray.indexOf(element['filename']) == -1 && (fs.statSync(element['filename']).size > 1024)) {
newArray.push(element['filename'])
arrObj.push(element)
} else if (newArray.indexOf(element['filename']) == -1 && (fs.statSync(element['filename']).size <= 1024)) {
let pathDir = path.dirname(element['output'])
createTimeFile(pathDir)//判斷存放壓縮的文件夾是否已經存在,不存在則創建
fs.createReadStream(element['filename']).pipe(fs.createWriteStream(element['output']))
console.log(`圖片${element['filename']}記憶體過小,直接轉移到${element['output']}`)
}
}
return arrObj
}
//png壓縮圖片
function pngCompress(arr, index) {
//壓縮結束
if (index < 0) {
console.log("\n本視窗在5秒後關閉!")
setTimeout(() => {
inputVlaue.close()
}, 5000)
return
}
let pathDir = path.dirname(arr[index]['output'])
let filename = arr[index]['filename']
createTimeFile(pathDir)
imagemin([filename], {
destination: pathDir,
plugins: [
imageminPngquant({
quality: [0.6, 0.7]
})
]
}).then(() => {
console.log(`圖片${filename}壓縮完成!`);
pngCompress(arr, index - 1)
}).catch(err => {
console.log(`${arr[index]['filename']}圖片壓縮不了了,直接轉移到${arr[index]['output']}`)
fs.createReadStream(arr[index]['filename']).pipe(fs.createWriteStream(arr[index]['output']))
pngCompress(arr, index - 1)
});
}
setCompress()
git地址:https://gitee.com/KingSio/project-template/tree/master/