一: 删除垃圾图片
思路:
- 获取 oss 中存储的所有图片文件;
- 获取数据库中存储的图片文件数据;
- 对比差异,不在数据库中的 oss 图片文件即为要删除的垃圾图片。
实现:
1、获取所有 oss 文件
import OSS from 'ali-oss'
import prisma from '@/services/index'import config from '@/config'
const { aliAccessKey, aliAccessKeySecret, ossBucketName, ossRegion } = configimport 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 = [] } = resultfor (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 = cronExpressionthis.task = taskthis.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 设为 nullif (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 删除结果