const path = require('path'); const sharp = require('sharp'); // 压缩配置 const compressOptions = { quality: 0.7, maxHeight: 800, maxWidth: 600 }; /** * 安全检查:防止路径遍历攻击(如 ../../etc/passwd) * @param {string} targetPath 目标文件路径 * @param {string} baseDir 基础目录 * @returns {boolean} 是否合法 */ function isSafePath(targetPath, baseDir) { const resolvedTarget = path.resolve(targetPath).toLowerCase(); const resolvedBase = path.resolve(baseDir).toLowerCase(); return resolvedTarget.startsWith(resolvedBase); } /** * 发送响应 * @param {ServerResponse} res 响应对象 * @param {number} statusCode 状态码 * @param {string} message 信息 */ function sendResponse(res, statusCode, message) { res.writeHead(statusCode, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end(message); } /** * 处理图片压缩和调整大小 * @param {string} imagePath 图片路径 * @param {Object} query 查询参数 * @returns {Promise} 处理后的图片Buffer */ async function processImage(imagePath, query) { let sharpInstance = sharp(imagePath).rotate(); // 处理宽高参数 let targetWidth = parseInt(query.w) || parseInt(query.width); let targetHeight = parseInt(query.h) || parseInt(query.height); // 如果没有指定宽高,使用配置的默认最大宽高 if (!targetWidth && !targetHeight) { targetWidth = compressOptions.maxWidth; targetHeight = compressOptions.maxHeight; } // 如果指定了宽高,进行调整大小处理 if (targetWidth || targetHeight) { const resizeOptions = { width: targetWidth, height: targetHeight, fit: sharp.fit.inside, // 保持宽高比,图片会完整显示在指定区域内 withoutEnlargement: true // 不放大比原始尺寸小的图片 }; sharpInstance = sharpInstance.resize(resizeOptions); } // 处理质量参数(优先使用查询参数,否则使用配置的默认值) const quality = query.q ? Math.max(1, Math.min(100, parseInt(query.q))) : Math.round(compressOptions.quality * 100); const finalQuality = Math.max(1, Math.min(100, quality)); // 转换为JPEG格式并压缩 return sharpInstance.jpeg({quality: finalQuality, mozjpeg: true}).toBuffer(); } module.exports = { isSafePath, sendResponse, processImage }