From 33ccc83615f5c74730adbadfff573dd100a8f86e Mon Sep 17 00:00:00 2001 From: LaoShui <79132480+laoshuikaixue@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:57:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(cloud):=20=E8=A7=A3=E5=86=B3=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=96=87=E4=BB=B6=E6=B8=85=E7=90=86=E5=92=8C=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E6=93=8D=E4=BD=9C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加异步临时文件清理函数避免资源泄露 - 将同步文件操作改为异步操作提高性能 - 在令牌分配失败时执行临时文件清理 - 在上传失败时确保临时文件被清理 - 使用 Promise 包装 MD5 计算操作 - 统一临时文件清理逻辑到 finally 块 --- module/cloud.js | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/module/cloud.js b/module/cloud.js index 3b8913e..2f80fc8 100644 --- a/module/cloud.js +++ b/module/cloud.js @@ -32,9 +32,32 @@ module.exports = async (query, request) => { let fileSize = query.songFile.size let fileMd5 = query.songFile.md5 + const cleanupTempFile = async () => { + if (useTempFile) { + try { + await fs.promises.unlink(query.songFile.tempFilePath) + } catch (e) { + logger.info('Temp file cleanup failed:', e.message) + } + } + } + if (useTempFile) { - const stats = fs.statSync(query.songFile.tempFilePath) - fileSize = stats.size + try { + const stats = await fs.promises.stat(query.songFile.tempFilePath) + fileSize = stats.size + } catch (e) { + logger.error('Failed to stat temp file:', e.message) + await cleanupTempFile() + return Promise.reject({ + status: 500, + body: { + code: 500, + msg: '临时文件访问失败', + detail: e.message, + }, + }) + } if (!fileMd5) { fileMd5 = await new Promise((resolve, reject) => { const hash = crypto.createHash('md5') @@ -46,7 +69,11 @@ module.exports = async (query, request) => { } } else { if (!fileMd5) { - fileMd5 = crypto.createHash('md5').update(query.songFile.data).digest('hex') + fileMd5 = await new Promise((resolve) => { + setImmediate(() => { + resolve(crypto.createHash('md5').update(query.songFile.data).digest('hex')) + }) + }) } fileSize = query.songFile.data.byteLength } @@ -109,6 +136,7 @@ module.exports = async (query, request) => { if (!tokenRes.body.result || !tokenRes.body.result.resourceId) { logger.error('Token allocation failed:', tokenRes.body) + await cleanupTempFile() return Promise.reject({ status: 500, body: { @@ -126,19 +154,15 @@ module.exports = async (query, request) => { logger.info('Upload completed:', uploadInfo?.body?.result?.resourceId) } catch (uploadError) { logger.error('Upload failed:', uploadError) + await cleanupTempFile() return Promise.reject(uploadError) - } finally { - if (useTempFile && fs.existsSync(query.songFile.tempFilePath)) { - fs.unlinkSync(query.songFile.tempFilePath) - } } } else { logger.info('File already exists, skip upload') - if (useTempFile && fs.existsSync(query.songFile.tempFilePath)) { - fs.unlinkSync(query.songFile.tempFilePath) - } } + await cleanupTempFile() + const res2 = await request( `/api/upload/cloud/info/v2`, {