如何通过公网图片URL跨服务向NestJS服务器上传图片
问题根因
你的S2服务上传代码存在4处错误,直接导致S1的FileInterceptor无法解析到文件:
- 变量顺序与重名错误:先执行
fetch(url)时url变量尚未赋值,后续又将上传接口地址赋值给url覆盖了图片地址,逻辑完全混乱 - 未初始化form实例:代码直接调用
form.append()但未提前创建FormData实例,运行时会直接抛出引用错误 - 未指定文件filename属性:
FileInterceptor底层基于multer实现,只有multipart表单中携带filename属性的字段才会被识别为文件,你append时仅传入流/Buffer内容,未指定文件名,字段会被判定为普通表单项,最终@UploadedFile()返回undefined - Header冲突:你手动合并的自定义header可能覆盖form-data自动生成的
content-type: multipart/form-data; boundary=xxx头,导致S1侧无法按multipart格式解析请求体
修复后代码
S2侧上传逻辑修正如下:
import * as FormData from 'form-data'; import fetch from "node-fetch"; // 其余依赖(HttpService、firstValueFrom、HttpException等)保持原有引入即可 // 1. 区分两个地址变量,禁止重名 const IMAGE_PUBLIC_URL = "替换为你要上传的图片公网可访问地址"; const UPLOAD_API_URL = "http://localhost:8000/api/v1/ticketing/uploads?filename=checking.jpg"; // 2. 拉取远程图片二进制内容 const imageResp = await fetch(IMAGE_PUBLIC_URL); const imageBuffer = await imageResp.buffer(); // 3. 初始化表单实例 const form = new FormData(); // 4. 追加文件字段,必须传入第三个参数指定文件名和文件类型 form.append("file", imageBuffer, { filename: "checking.jpg", contentType: "image/jpeg" }); // 5. 发起请求,仅使用form自动生成的headers,避免content-type/boundary冲突 return firstValueFrom( this.httpService.post(UPLOAD_API_URL, form, { headers: { // 如有鉴权需求可在这里加自定义头,比如 Authorization: xxx,不要手动设置content-type ...form.getHeaders() } }).pipe( map((resp) => resp.data), catchError((err) => { throw new HttpException( {success: false, error: {message: "upload failed"}, payload: err.response?.data}, HttpStatus.BAD_REQUEST, ); }) ) );
额外排查项
如果修正后S1仍接收不到file,检查以下配置:
- 确认S1的
FileInterceptor未配置过小的limits.fileSize,图片体积超过限制会被multer直接拦截 - 确认S1的
main.ts中没有全局注册的urlencoded/json等body-parser提前处理multipart请求,multer只能解析未被预处理过的原始multipart请求体 - 确认上传接口路由地址正确,没有漏写全局前缀导致请求打到错误路由
内容的提问来源于stack exchange,提问作者Prakhar Dev Gupta
相关产品推荐
相关产品推荐

