背景

有一个项目,Node(Egg)+ Vue,服务端接口通过Node转发。 服务端新增了一个文件上传表单接口,但是前后端联调的时候怎么都调试不通。

Step 通过Postman测试

服务端form表单两个字段

通过Postman测试服务端接口,没问题,可以分别通过$_POST,$_FILES拿到type,source。 那就是前段调用的问题。

Web层问题?

前端的写法也是标准写法,所以感觉问题不在web层,而在Node层。

Node层问题

Node层,通过Proxy对请求的header和body做了个性化处理,但是发现没有对multipart做支持。

支持文件上传

尝试单独处理该接口,构建form表单提交。

   } else if (ctx.path.indexOf('uploadExcel') !== -1) {
      const stream = await ctx.getFileStream();
      const fieldsType = stream.fields && stream.fields.type;

      let form = new FormData()
      form.append('type', fieldsType)
      form.append('source', stream)

      let opt = parseRequest(options, url, ctx);
      // @ts-ignore
      opt.data = form

      let res = await urllib.request(opt.uri, opt);
      ctx.body = res.data;

服务端还是拿不到,通过tcpflow抓包,发现http body是把stream对象作为字符串传递过去了

{"_overheadLength":248,"_valueLength":1,"_valuesToMeasure":[],"writable":false,"readable":true,"dataSize":0,"maxDataSize":2097152,"pauseStreams":true,"_released":false,"_streams":["----------------------------511334654748913548825165\\\\r\\\\nContent-Disposition: form-data; name=\\\\"type\\\\"\\\\r\\\\n\\\\r\\\\n","1",null,"----------------------------511334654748913548825165\\\\r\\\\nContent-Disposition: form-data; name=\\\\"source\\\\"\\\\r\\\\nContent-Type: application/octet-stream\\\\r\\\\n\\\\r\\\\n",{"source":{"_readableState":{"objectMode":false,"highWaterMark":16384,"buffer":{"head":{"data":{"type":"Buffer","data":[49,10,50,10,51,10]},"next":null},"tail":{"data":{"type":"Buffer","data":[49,10,50,10,51,10]},"next":null},"length":1},"length":6,"pipes":null,"pipesCount":0,"flowing":false,"ended":true,"endEmitted":false,"reading":false,"sync":false,"needReadable":false,"emittedReadable":true,"readableListening":false,"resumeScheduled":false,"destroyed":false,"defaultEncoding":"utf8","awaitDrain":0,"readingMore":false,"decoder":null,"encoding":null},"readable":true,"domain":null,"_events":{},"_eventsCount":4,"truncated":false,"fieldname":"source","filename":"test.xlsx","encoding":"7bit","transferEncoding":"7bit","mime":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","mimeType":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","fields":{"type":"1"}},"dataSize":0,"maxDataSize":null,"pauseStream":true,"_maxDataSizeExceeded":false,"_released":false,"_bufferedEvents":[{"0":"pause"}],"_events":{},"_eventsCount":1},null],"_currentStream":null,"_insideLoop":false,"_pendingNext":false,"_boundary":"--------------------------511334654748913548825165"}

看urlib API,是参数用错了,应该是

opt.stream = form

<https://github.com/node-modules/urllib>
data Object - Data to be sent. Will be stringify automatically.
stream stream.Readable - Stream to be pipe to the remote. If set, data and content will be ignored.