一: 删除垃圾图片
思路:
- 获取 oss 中存储的所有图片文件;
- 获取数据库中存储的图片文件数据;
- 对比差异,不在数据库中的 oss 图片文件即为要删除的垃圾图片。
实现:
1、获取所有 oss 文件
import OSS from 'ali-oss'
import prisma from '@/services/index'
import config from '@/config'
const { aliAccessKey, aliAccessKeySecret, ossBucketName, ossRegion } = config
import TaskOssScheduler from './schedule'
const client = new OSS({
region: ossRegion,
accessKeyId: aliAccessKey,
accessKeySecret: aliAccessKeySecret,
bucket: ossBucketName
})
/**
* @description 获取 oss 下的图片
* @param other
* @returns
*/
export const getAllImgFromOss: any = async (other: any = {}) => {
try {
let continuationToken = null;
let imgArray: string[] = []
// 每页列举1000个文件。
const maxKeys = '5';
do {
const result: any = await client.listV2({
delimiter: '/',
prefix: 'web/',
'start-after': 'web/', // web/ 目录之后的文件
'continuation-token': continuationToken,
'max-keys': maxKeys,
...other
}, {});
continuationToken = result.nextContinuationToken;
const { objects = [] } = result
for (let i = 0; i < objects.length; i++) {
imgArray.push(objects[i].name);
}
console.log(result);
} while (continuationToken)
return {
list: imgArray,
count: imgArray.length || 0,
}
} catch (error) {
console.log(error);
return []
}
}
2、获取所有数据存储的图片数据
/**
* 从数据库中获取图片
*/
export const getAllImgFromModel = async () => {
try {
let dataBaseImgs: any = []
// todo 未来查询多表
const imgList = await prisma.applySitter.findMany({
select: {
idCardFrontUrl: true,
idCardBackUrl: true,
groomerImgUrl: true,
manAndPetPhotoUrl: true,
}
})
// 平铺返回值并替换路径域名部分
imgList.map(item => {
const items = Object.values(item).map(itemMap => itemMap?.replace('https://xxxx.com/', ''))
dataBaseImgs.push(...items)
})
console.log(dataBaseImgs);
return dataBaseImgs
} catch (error) {
return []
}
}
// 删除 oss 图片
export const delOssImgs = async (imgArr: string[]) => {
try {
const result = await client.deleteMulti(imgArr, { quiet: true });
return result
} catch (error) {
throw error
}
}
3、对比差异,找到要删除的图片
// 删除 oss 垃圾图片
export const delOssBadImgs = async () => {
try {
// 获取 oss 文件列表,
// todo 暂时只获取 web 目录下图片
// 1. oss 图片
const ossResult = await getAllImgFromOss() || {}
// 2. 存储到数据库图片
const dataBaseResult = await getAllImgFromModel() || []
// 3. 对比差异
const badImgArr: string[] = []
ossResult.list.forEach((arrItem: string) => {
if (arrItem && !dataBaseResult.includes(arrItem)) {
badImgArr.push(arrItem)
}
})
// 4. 删除指定图片
const delRes = await delOssImgs(badImgArr)
// console.log('--->badImg');
// console.log(badImgArr);
if (delRes?.res.status === 200) {
console.log('删除 oss 垃圾图片成功')
} else {
console.log('删除 oss 垃圾图片失败')
}
} catch (error) {
}
}
二: 创建定时任务
1、安装依赖包 npm i node-schedule @types/node-schedule -S
node-schedule 为创建定时任务第三方库
2、创建定时任务基类文件 taskOssScheduler.ts
import schedule from 'node-schedule'
import dayjs from 'dayjs'
import type { Job, JobCallback } from 'node-schedule';
// 定时任务基类
export default class TaskOssScheduler {
cronExpression: string;
task: JobCallback;
job: Job | null;
constructor(cronExpression: string, task: any) {
this.cronExpression = cronExpression
this.task = task
this.job = null
}
// 启动任务
start() {
// 如果当前没有正在运行的任务,则创建新的任务
if (!this.job) {
this.job = schedule.scheduleJob(this.cronExpression, this.task);
console.log(`定时任务启动: ${this.cronExpression}`);
console.log(dayjs().format('YYYYMMDD-HH:mm:ss'));
} else {
this.stop()
}
}
// 停止任务
stop() {
// 如果当前有正在运行的任务,则取消任务并将 job 设为 null
if (this.job) {
this.job.cancel();
console.log(`定时任务停止: ${this.cronExpression}`);
console.log(dayjs().format('YYYYMMDD-HH:mm:ss'));
this.job = null;
}
}
}
3、定义工具函数
// 每天的凌晨 2 点进行删除
// 入参任务开始时间及回调函数
export const DelOssImgTask = new TaskOssScheduler('0 0 2 * * *', delOssBadImgs)
4、定义 express 路由,通过访问路由,开启和关闭定时任务
ossController:
startDelOssImgTask: async (req: Request, res: Response) => {
try {
// 开启定时删除 oss 垃圾图片任务
DelOssImgTask.start()
res.send(ComResult.success('定时任务开启'))
} catch (error) {
throw error
}
},
stopDelOssImgTask: async (req: Request, res: Response) => {
try {
// 关闭定时删除 oss 垃圾图片任务
DelOssImgTask.stop()
res.send(ComResult.success('定时任务关闭'))
} catch (error) {
throw error
}
}
ossRoutes:
ossRoutes.post('/startDelOssImgTask', ossController.startDelOssImgTask)
ossRoutes.post('/stopDelOssImgTask', ossController.stopDelOssImgTask)
三、测试
oss 删除结果