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

流管道完成后如何返回响应?Koa自定义文件服务器返回异常求助

解决Koa自定义文件服务器流式返回图片时显示“Not found”的问题

咱们先梳理下你遇到的问题:自己实现Koa文件服务器(不用koa-static),但请求dest.jpg时只返回“Not found”,客户端用request.post配合流来接收文件。下面我帮你排查问题并给出完整的实现方案。

常见问题原因

  • 服务器路由路径和客户端请求路径不匹配
  • 没有正确检查目标文件是否存在,直接返回了404
  • 流式传输逻辑错误,没有将文件流正确pipe到响应对象
  • 未设置正确的响应头(比如图片的Content-Type)

完整实现代码

服务器端代码

const Koa = require('koa');
const Router = require('koa-router');
const HttpStatus = require('http-status');
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');
const koaBody = require('koa-body');

const app = new Koa();
const router = new Router();

// 解析请求体
app.use(koaBody());

// 处理文件请求的路由,这里假设请求路径是 /file/:filename
router.get('/file/:filename', async (ctx) => {
  const { filename } = ctx.params;
  // 定义文件的绝对路径,避免路径遍历漏洞
  const filePath = path.resolve(__dirname, './', filename);

  try {
    // 先检查文件是否存在且可读取
    await fs.access(filePath, fsSync.constants.R_OK);
    
    // 设置正确的响应头,图片类型设为image/jpeg
    ctx.set('Content-Type', 'image/jpeg');
    ctx.status = HttpStatus.OK;

    // 创建文件可读流,pipe到响应对象实现流式返回
    const readStream = fsSync.createReadStream(filePath);
    ctx.body = readStream;
  } catch (err) {
    // 文件不存在或不可读时返回404
    ctx.status = HttpStatus.NOT_FOUND;
    ctx.body = 'Not found';
  }
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
  console.log('服务器运行在 http://localhost:3000');
});

客户端代码

const request = require('request');
const fs = require('fs');

// 注意请求路径要和服务器路由匹配,这里用GET请求(获取文件通常用GET)
const readStream = request.get('http://localhost:3000/file/dest.jpg');
const tempSaveFile = fs.createWriteStream('dest.jpg');

// 处理流式传输
readStream.pipe(tempSaveFile);

// 监听流的结束和错误事件
tempSaveFile.on('finish', () => {
  console.log('文件下载完成');
});

readStream.on('error', (err) => {
  console.error('请求出错:', err);
});

关键细节说明

  • 路径安全:用path.resolve生成绝对路径,避免恶意路径遍历攻击
  • 文件存在检查:用fs.access异步检查文件是否可读取,比直接创建流更稳妥
  • 响应头设置:必须设置正确的Content-Type,否则客户端可能无法正确解析图片
  • 请求方法:获取文件建议用GET方法,POST通常用于提交数据,这也可能是你之前出错的原因之一

如果你的业务必须用POST请求,只需要把服务器端的router.get改成router.post,客户端保持request.post即可,但从REST规范来说,获取资源用GET更合理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:34:53