feat:增加更改图片大小功能
This commit is contained in:
64
app.js
64
app.js
@@ -1,38 +1,17 @@
|
||||
require('dotenv').config();
|
||||
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const sharp = require('sharp');
|
||||
const {sendResponse, isSafePath, processImage} = require("./utils");
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
const IMAGE_BASE_DIR = process.env.IMAGE_BASE_DIR || '/app/images';
|
||||
|
||||
/**
|
||||
* 安全检查:防止路径遍历攻击(如 ../../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 {http.ServerResponse} res 响应对象
|
||||
* @param {number} statusCode 状态码
|
||||
* @param {string} message 错误信息
|
||||
*/
|
||||
function sendError(res, statusCode, message) {
|
||||
res.writeHead(statusCode, { 'Content-Type': 'text/plain; charset=utf-8' });
|
||||
res.end(message);
|
||||
}
|
||||
|
||||
const server = http.createServer(async (req, res) => {
|
||||
if (req.method !== 'GET') {
|
||||
return sendError(res, 405, '仅支持GET请求');
|
||||
return sendResponse(res, 405, '仅支持GET请求');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -42,13 +21,7 @@ const server = http.createServer(async (req, res) => {
|
||||
|
||||
// 过滤根路径请求(避免直接访问服务根目录)
|
||||
if (requestPath === '/') {
|
||||
return sendError(res, 200, `
|
||||
图片处理服务已启动!
|
||||
使用示例:
|
||||
1. 访问原图片:http://localhost:${PORT}/a/b/c.png
|
||||
2. 调整质量:http://localhost:${PORT}/a/b/c.png?q=80
|
||||
图片基础目录:${IMAGE_BASE_DIR}
|
||||
`);
|
||||
return sendResponse(res, 200, '图片处理服务已启动!');
|
||||
}
|
||||
|
||||
const requestedFilePath = requestPath.slice(1);
|
||||
@@ -56,42 +29,39 @@ const server = http.createServer(async (req, res) => {
|
||||
|
||||
// 安全检查:防止路径遍历
|
||||
if (!isSafePath(fullImagePath, IMAGE_BASE_DIR)) {
|
||||
return sendError(res, 403, '访问拒绝:非法路径(路径遍历攻击)');
|
||||
return sendResponse(res, 403, '访问拒绝:非法路径(路径遍历攻击)');
|
||||
}
|
||||
|
||||
if (!fs.existsSync(fullImagePath)) {
|
||||
return sendError(res, 404, `图片不存在:${requestedFilePath}`);
|
||||
return sendResponse(res, 404, `图片不存在:${requestedFilePath}`);
|
||||
}
|
||||
|
||||
if (!query.q) {
|
||||
// 如果没有压缩参数,直接返回原图
|
||||
if (!query.q && !query.w && !query.width && !query.h && !query.height) {
|
||||
const fileStream = fs.createReadStream(fullImagePath);
|
||||
const ext = path.extname(fullImagePath).slice(1); // 如 png/jpg
|
||||
res.writeHead(200, { 'Content-Type': `image/${ext}` });
|
||||
const ext = path.extname(fullImagePath).slice(1);
|
||||
res.writeHead(200, {'Content-Type': `image/${ext}`});
|
||||
// 流式传输文件(适合大文件)
|
||||
fileStream.pipe(res);
|
||||
fileStream.on('error', (err) => {
|
||||
sendError(res, 500, `读取文件失败:${err.message}`);
|
||||
sendResponse(res, 500, `读取文件失败:${err.message}`);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const quality = parseInt(query.q);
|
||||
if (isNaN(quality)) {
|
||||
return sendError(res, 400, '质量参数q必须是数字(1-100)');
|
||||
}
|
||||
const finalQuality = Math.max(1, Math.min(100, quality));
|
||||
|
||||
const imageBuffer = await sharp(fullImagePath).rotate().jpeg({ quality: finalQuality }).toBuffer();
|
||||
// 处理图片压缩和调整大小
|
||||
const imageBuffer = await processImage(fullImagePath, query);
|
||||
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'image/jpeg',
|
||||
'Content-Length': imageBuffer.length
|
||||
'Content-Length': imageBuffer.length,
|
||||
'Cache-Control': 'public, max-age=86400' // 缓存1天
|
||||
});
|
||||
res.end(imageBuffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error('服务器异常:', error);
|
||||
sendError(res, 500, `服务器内部错误:${error.message}`);
|
||||
sendResponse(res, 500, `服务器内部错误:${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user