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

文件上传至API排序时触发500内部服务器错误,求排查

问题分析与修复方案

问题描述

尝试将文件上传至运行在3000端口的API,对文件中的数字排序后生成可下载的结果文件,但上传后触发计算时出现Internal Server Error(500内部服务器错误)。React应用运行在3001端口,以下是两端代码及问题排查:


原API代码(app.js)

const express = require('express');
const multer = require('multer');
const bodyParser = require('body-parser');
const fs = require('fs');
const app = express();

const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

app.use(bodyParser.text({ type: 'text/plain' }));

app.post('/sort', upload.single('inputFile'), (req, res) => {
    console.log(req.file)
    const input = req.file.buffer.toString().split('\n').map(Number);
    const result = input.sort((a, b) => b - a);
    const resultText = result.join('\n');
    fs.writeFile('result.txt', resultText, (err) => {
        if(err) throw err;
        res.send('File succesfully sorted!');
    });
    res.set('Content-Type', 'text/plain');
    res.send(resultText);
});

app.listen(3000, () => {
    console.log('API is listening on port 3000');
});

原React代码(App.js片段)

const [inputFile, setInputFile] = useState(null);
const [result, setResult] = useState(null);
const [processingTime, setProcessingTime] = useState(null);

const handleFileUpload = (event) => {
  setInputFile(event.target.files[0]);
};

const startCalculation = async (event) => {
  event.preventDefault();
  const startTime = performance.now();
  const formData = new FormData();
  formData.append('inputFile', inputFile);
  console.log(inputFile)

  const response = await fetch("http://localhost:3000/sort", {
    method: 'POST',
    body: formData,
    mode: 'no-cors',
  });

  const data = await response.text();
  console.log(data);
  setResult(data);
  setProcessingTime(performance.now() - startTime);

};

const handleDownload = (event) => {
  event.preventDefault();
  const file = new Blob([result], {
    type: 'text/plain'
  });
  const fileURL = URL.createObjectURL(file);
  const link = document.createElement('a');
  link.href = fileURL;
  link.download = 'result.txt';
  link.click();
};

核心问题与修复步骤

1. API端的致命错误

  • 重复发送响应:代码中先后调用两次res.send,HTTP响应仅能发送一次,重复调用直接触发服务器错误。
  • bodyParser与multer冲突:bodyParser.text会尝试解析所有请求为文本,干扰multer对multipart/form-data格式文件的解析,导致req.file为undefined,后续访问buffer时报错。
  • 错误处理不当:fs.writeFile回调中直接throw err会终止服务器进程,应返回错误响应给客户端。
  • 未处理无效数据:文件中的空行或非数字内容会被转为NaN,导致排序逻辑异常。
  • 跨域未配置:React与API端口不同,未配置CORS会引发跨域限制。

2. React端的错误

  • mode: 'no-cors'限制响应读取:该模式下浏览器会屏蔽响应内容,response.text()会失败,无法感知服务器错误。
  • 未检查文件是否存在:用户未选文件就提交时,formData无文件字段,API端req.file为undefined触发报错。
  • 未处理响应错误状态:未判断response.ok,服务器返回500错误时仍尝试读取内容,导致前端报错。

修复后的代码

修复后的API代码(app.js)

先安装cors依赖:

npm install cors
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const cors = require('cors');
const app = express();

// 配置CORS允许3001端口跨域访问
app.use(cors({ origin: 'http://localhost:3001' }));

const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

// 移除干扰multer的bodyParser.text配置
// app.use(bodyParser.text({ type: 'text/plain' }));

app.post('/sort', upload.single('inputFile'), (req, res) => {
    // 检查是否接收到文件
    if (!req.file) {
        return res.status(400).send('请上传文件');
    }

    try {
        // 解析文件并过滤无效内容
        const input = req.file.buffer.toString()
            .split('\n')
            .map(str => str.trim())
            .filter(str => str)
            .map(Number)
            .filter(num => !isNaN(num));

        // 降序排序
        const result = input.sort((a, b) => b - a);
        const resultText = result.join('\n');

        // 保存结果到服务器(可选,不需要可删除这段)
        fs.writeFile('result.txt', resultText, (err) => {
            if (err) {
                console.error('保存文件失败:', err);
                return res.status(500).send('保存结果文件失败');
            }
            res.set('Content-Type', 'text/plain');
            res.send(resultText);
        });

        // 无需保存到服务器的话,直接返回结果
        // res.set('Content-Type', 'text/plain');
        // res.send(resultText);
    } catch (err) {
        console.error('处理文件失败:', err);
        res.status(500).send('处理文件时发生错误');
    }
});

app.listen(3000, () => {
    console.log('API is listening on port 3000');
});

修复后的React代码(App.js片段)

const [inputFile, setInputFile] = useState(null);
const [result, setResult] = useState(null);
const [processingTime, setProcessingTime] = useState(null);
const [error, setError] = useState(''); // 新增错误提示状态

const handleFileUpload = (event) => {
  setInputFile(event.target.files[0]);
  setError(''); // 选择文件后清空错误提示
};

const startCalculation = async (event) => {
  event.preventDefault();
  // 检查是否选择文件
  if (!inputFile) {
    setError('请先选择要上传的文件');
    return;
  }

  const startTime = performance.now();
  const formData = new FormData();
  formData.append('inputFile', inputFile);

  try {
    const response = await fetch("http://localhost:3000/sort", {
      method: 'POST',
      body: formData,
      // 移除no-cors模式,允许跨域请求
    });

    if (!response.ok) {
      const errText = await response.text();
      throw new Error(errText || '服务器处理失败');
    }

    const data = await response.text();
    setResult(data);
    setProcessingTime(performance.now() - startTime);
    setError('');
  } catch (err) {
    console.error('请求失败:', err);
    setError(err.message);
    setResult(null);
  }
};

const handleDownload = (event) => {
  event.preventDefault();
  if (!result) return;
  
  const file = new Blob([result], { type: 'text/plain' });
  const fileURL = URL.createObjectURL(file);
  const link = document.createElement('a');
  link.href = fileURL;
  link.download = 'result.txt';
  link.click();
  // 释放URL对象,避免内存泄漏
  URL.revokeObjectURL(fileURL);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:31:58