使用webp-converter转换WebP为PNG时遇“无法打开输入文件”错误
问题分析与解决方案
核心错误点
- setTimeout延迟参数位置错误:你把
14000传给了forEach的第二个参数(用于绑定this值),而非setTimeout的延迟时间,导致定时器无延迟触发,还可能引发逻辑混乱。 - 相对路径导致文件查找失败:使用
temp/image${attachment.id}.webp这类相对路径时,webp-converter会从自身bin目录出发查找文件,而非你的项目根目录,从而找不到已下载的WebP文件。 - webp.dwebp选项重复:
"-quiet -quiet"是无效参数,重复的安静模式选项会干扰命令执行。
修正后的代码
const fs = require('fs'); const path = require('path'); const request = require('request'); // 建议替换为axios/node-fetch,request已弃用 const webp = require('webp-converter'); const { Events } = require('discord.js'); let timer; client.on(Events.MessageUpdate, (oldMessage, newMessage) => { newMessage.attachments.forEach((attachment) => { if (attachment.url && attachment.url.endsWith('.webp')) { // 增加WebP格式校验 clearTimeout(timer); // 把延迟时间放到setTimeout的第二个参数位置 timer = setTimeout(() => { // 生成绝对路径,避免目录查找错误 const tempDir = path.join(__dirname, 'temp'); // 确保temp目录存在 if (!fs.existsSync(tempDir)) { fs.mkdirSync(tempDir, { recursive: true }); } const webpPath = path.join(tempDir, `image${attachment.id}.webp`); const pngPath = path.join(tempDir, `image${attachment.id}.png`); // 下载WebP图片 request(attachment.url) .pipe(fs.createWriteStream(webpPath)) .on('close', () => { console.log(`Image downloaded to ${webpPath}`); // 转换WebP为PNG,修正选项参数 webp.dwebp( webpPath, pngPath, '-quiet', (status, error) => { if (status === 100) { console.log(`Successfully converted to PNG: ${pngPath}`); // 这里可以添加发送PNG到客户端的逻辑 } else { console.error('Conversion failed:', error); } } ); }) .on('error', (err) => { console.error('Download failed:', err); }); }, 14000); // 正确的延迟时间位置 } }); // 移除forEach后的多余参数14000 });
额外优化建议
- 替换request库:request已正式弃用,推荐使用
axios或node-fetch实现文件下载,示例用axios的写法:const axios = require('axios'); // 替换下载部分的代码 axios({ url: attachment.url, method: 'GET', responseType: 'stream' }).then(response => { response.data.pipe(fs.createWriteStream(webpPath)) .on('close', () => { // 转换逻辑 }) .on('error', err => console.error('Download error:', err)); }).catch(err => console.error('Axios request error:', err)); - 清理临时文件:转换完成后可以定时清理temp目录下的旧文件,避免磁盘空间占用过多。
- 格式校验:增加对附件格式的判断(如
attachment.url.endsWith('.webp')),避免处理非WebP文件。
内容的提问来源于stack exchange,提问作者Jake S
相关产品推荐
相关产品推荐

