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

NestJS调用Synology Upload API超时及FormData报错问题排查

NestJS调用Synology FileStation上传API超时及FormData报错排查

问题描述

使用NestJS调用Synology FileStation Upload API上传文件时,请求始终无响应直至超时。改用import * as FormData from 'form-data'并使用formData.getHeaders()时,执行formData.append('file', file)又触发source.on is not a function错误。以下是相关代码及超时响应信息,寻求问题排查方案。

代码示例

// Service
import { HttpService } from '@nestjs/axios';

constructor(private readonly http: HttpService) {}

async uploadFile(files: File[], file_path: string) {
  try {
    const formData = new FormData();
    for (const file of files) {
      formData.append('file', file);
    }

    const data = await firstValueFrom(
      this.http
        .post(process.env.SYNOLOGY_URL, formData, {
          params: {
            api: 'SYNO.FileStation.Upload',
            version: 2,
            method: 'upload',
            _sid: this.sid,
            path: file_path,
            create_parents: false,
            overwrite: false,
          },
        })
        .pipe(map((response) => response.data)),
    );
  } catch (error) {
    console.error(JSON.stringify(error, null, 2));
  }
}

超时响应信息

{
  "message": "timeout of 10000ms exceeded",
  "name": "AxiosError",
  "stack": "AxiosError: timeout of 10000ms exceeded\n    at RedirectableRequest.handleRequestTimeout (/usr/projects/backend/init_nestjs/node_modules/axios/lib/adapters/http.js:647:16)\n    at RedirectableRequest.emit (node:events:518:28)\n    at Timeout.<anonymous> (/usr/projects/backend/init_nestjs/node_modules/follow-redirects/index.js:210:12)\n    at listOnTimeout (node:internal/timers:573:17)\n    at processTimers (node:internal/timers:514:7)\n    at Axios.request (/usr/projects/backend/init_nestjs/node_modules/axios/lib/core/Axios.js:45:41)",
  "config": {
    "transitional": {
      "silentJSONParsing": true,
      "forcedJSONParsing": true,
      "clarifyTimeoutError": false
    },
    "adapter": [
      "xhr",
      "http"
    ],
    "transformRequest": [
      null
    ],
    "transformResponse": [
      null
    ],
    "timeout": 10000,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1,
    "maxBodyLength": -1,
    "env": {},
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "Content-Type": "multipart/form-data; boundary=axiosaxios-1.6.8-boundary-KyPk5XLtcOCa_vHTRUxIf-PRY",
      "User-Agent": "axios/1.6.8",
      "Content-Length": "263074",
      "Accept-Encoding": "gzip, compress, deflate, br"
    },
    "maxRedirects": 5,
    "params": {
      "api": "SYNO.FileStation.Upload",
      "version": 2,
      "method": "upload",
      "_sid": "SYNOLOGY_SID",
      "path": "/docker",
      "create_parents": false,
      "overwrite": false
    },
    "method": "post",
    "url": "SYNOLOGY_URL/webapi/entry.cgi",
    "data": {}
  },
  "code": "ECONNABORTED",
  "status": null
}

问题分析与解决方案

1. 请求超时问题

超时核心原因大概率是Axios自动生成的Content-Type头不符合Synology API要求,或请求参数/会话有效性存在问题:

  • 手动指定FormData Headers:Axios自动生成的multipart边界可能无法被Synology正确解析,改用form-data库的getHeaders()方法手动设置请求头
  • 验证会话有效性:确认_sid是当前有效会话ID,可通过Synology登录接口重新获取
  • 调整超时时间:默认10s可能不足,适当调高至30s或更久
  • 检查路径与权限:确认path参数对应目录存在且当前_sid关联用户有上传权限,可尝试设置create_parents: true自动创建目录

2. source.on is not a function报错问题

该错误是因为form-data库的append方法不直接支持NestJS(multer)传入的File对象,需将文件转换为可读流或Buffer:

  • 使用文件路径创建可读流(需确保multer配置了临时文件存储)
  • 直接使用file.buffer(multer会将文件内容读入Buffer)

修正后的完整代码

import { HttpService } from '@nestjs/axios';
import * as FormData from 'form-data';
import * as fs from 'fs';
import { firstValueFrom, map } from 'rxjs';

constructor(private readonly http: HttpService) {}

async uploadFile(files: Express.Multer.File[], file_path: string) {
  try {
    const formData = new FormData();
    for (const file of files) {
      // 方式1:使用可读流上传(需multer配置临时存储路径)
      formData.append('file', fs.createReadStream(file.path), {
        filename: file.originalname,
      });

      // 方式2:直接使用Buffer上传
      // formData.append('file', file.buffer, { filename: file.originalname });
    }

    const data = await firstValueFrom(
      this.http
        .post(process.env.SYNOLOGY_URL, formData, {
          params: {
            api: 'SYNO.FileStation.Upload',
            version: 2,
            method: 'upload',
            _sid: this.sid,
            path: file_path,
            create_parents: true, // 自动创建不存在的父目录
            overwrite: false,
          },
          headers: {
            ...formData.getHeaders(), // 手动注入FormData的headers
          },
          timeout: 30000, // 延长超时时间
        })
        .pipe(map((response) => response.data)),
    );

    console.log('上传成功:', data);
    return data;
  } catch (error) {
    console.error('上传失败:', JSON.stringify(error, null, 2));
    throw error;
  }
}

额外注意事项

  • 确认Synology设备与NestJS服务网络连通,防火墙未拦截5000/5001端口(默认Synology Web端口)
  • 若使用HTTPS访问,需确保Synology的SSL证书被信任,或在Axios配置中关闭证书验证(仅测试环境使用)
  • 批量上传时,检查Synology的文件大小限制,避免单文件或总大小超出限制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:10:04