You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js如何将文件名和尺寸作为查询参数传递实现图片缩放

问题根因定位

你遇到的报错直接原因是:在路由回调里定义了resizeImage异步函数后,直接return res.send(resizeImage),把函数本身作为参数传给了res.send,而res.send仅接受字符串、Buffer、JSON等类型的内容,不接受函数类型,因此直接抛出类型错误。

除此之外你的代码还存在几个隐性问题:

  • fs.promises.access是异步方法,现有getAccessToFiles用同步try/catch捕获不到错误,返回的判断结果完全无效
  • 图片路径拼接没有加路径分隔符,会出现xxx/imagesmyImage.jpg这类错误路径
  • 定义了exportImages指向uploads输出文件夹,但实际代码里把处理后的图片写到了原图片文件夹,不符合需求
  • 没有从请求中提取查询参数,也没有做参数合法性校验
修复步骤

1. 修改utilities.ts文件

把文件存在性校验改为异步逻辑,适配异步fs方法:

import { promises as fs } from "fs";

// 改为异步函数,正确校验文件是否存在
let getAccessToFiles = async (path: string): Promise<boolean> => {
    try {
        await fs.access(path)
        return true;
    } catch (err) {
        return false;
    }
}

let getFilesName = (
  imageToResize: string,
  width: number | null,
  height: number | null
): string => {
  let filename = imageToResize;
  if (width) {
    filename += `width${width}`;
  }
  if (height) {
    filename += `height${height}`;
    }
    
    return `${filename}.jpg`
};

export { getAccessToFiles, getFilesName };

2. 修改路由逻辑文件

补充参数提取、参数校验、路径修复、函数调用逻辑:

import express, { Request, Response, Router } from "express";
import path from "path";
import sharp from "sharp";
import { promises as fs } from "fs";
import { getAccessToFiles, getFilesName } from "../../utils/utilities";
const resizeImages: Router = Router();

// 定义输入输出路径
const importImages = path.resolve(__dirname, "images");
const exportImages = path.resolve(__dirname, "uploads");
// 提前创建输出文件夹,避免写入报错
fs.mkdir(exportImages, { recursive: true }).catch(err => console.log('创建输出文件夹失败', err));

resizeImages.get("/", async (req: Request, res: Response) => {
  // 提取查询参数
  const { filename, width, height } = req.query;
  // 参数合法性校验
  if (!filename) {
    return res.status(400).json({ error: "缺少必填参数filename" });
  }
  const parsedWidth = width ? Number(width) : null;
  const parsedHeight = height ? Number(height) : null;
  if (parsedWidth && isNaN(parsedWidth)) {
    return res.status(400).json({ error: "width必须为数字" });
  }
  if (parsedHeight && isNaN(parsedHeight)) {
    return res.status(400).json({ error: "height必须为数字" });
  }

  // 校验原图是否存在
  const originImagePath = path.join(importImages, `${filename}.jpg`);
  const isOriginExist = await getAccessToFiles(originImagePath);
  if (!isOriginExist) {
    return res.status(404).json({ error: "指定的原图不存在" });
  }

  const resizeImage = async (
    imageName: string,
    width: number | null,
    height: number | null
  ): Promise<string> => {
    const resizedImageName = getFilesName(imageName, width, height);
    const outputPath = path.join(exportImages, resizedImageName);
    // 已处理过的图片直接返回,避免重复处理
    const isResizedExist = await getAccessToFiles(outputPath);
    if (isResizedExist) {
      return resizedImageName;
    }
    try {
      await sharp(originImagePath)
        .resize(width, height)
        .jpeg()
        .toFile(outputPath);
    } catch (err) {
      res.status(400).json({ error: err});
      return ''
    }
    return resizedImageName;
  };
    
  // 调用处理函数,拿到结果后再返回给前端
  const resultName = await resizeImage(filename as string, parsedWidth, parsedHeight);
  if (resultName) {
    // 可选择返回文件名,或者直接返回图片文件
    res.send(`图片处理完成,文件名:${resultName}`)
    // 若要直接返回图片:res.sendFile(path.join(exportImages, resultName))
  }
});

export default resizeImages;
其他注意事项
  • 要确保images文件夹和代码文件的相对路径正确,如果TS编译后目录结构有变化,可以改用process.cwd()拼接项目根目录下的路径
  • app.use(express.json())不需要写在路由文件中,放在项目入口的全局配置里即可

内容的提问来源于stack exchange,提问作者fyardlest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:18:04