記錄一次node中臺轉發表單上傳文件到後臺過程

公司幾個項目都是三層架構模式即前臺,中臺(中間層),後臺。前臺微信端公衆號使用vue框架,後臺管理前端使用react,中臺(中間層)使用node,後臺使用java。這次說的是後臺關鍵上傳數據文件時遇到的一個bug,由於是三層架構,前臺表單會先提交到node中間層,而後再經過node中間層轉發到java後臺保存並讀取文件數據。 這次遇到了一個bug當表單提交到node中間層的時候node接口request能夠獲取獲得表單上傳的文件信息,就在node端建立http請求轉發到後臺的時候後臺報錯了:the request was rejected because no multipart boundary was found後臺收到的接口請求中得不到boundary信息,此時已肯定node建立的http請求中headers中Content-Type爲multipart/form-data,很顯然java後臺沒收到上傳文件信息,經過在頁面建立form表單使用後臺上傳接口地址發現後臺能夠上傳,這證實後臺接口沒問題,node中臺接口也能收到form表單上傳文件數據,那麼範圍進一步縮小問題就出如今node http請求轉發到後臺這步的問題了。既而後臺接口請求體中沒有boundary那麼問題就出如今建立請求的時候少給了東西后臺了,Google+百度了一下找到的解決方式在發現都不行,不能說徹底沒有用可是仍是找到了方向。後臺要的是表單數據,那node中臺轉發的時候就轉發一個表單數據。因而找到了form-data這個包及connect-multiparty中間件。 先插入一段代碼而後再分析;javascript

node-fetch方式發送請求到後臺

const fs = require('fs')
const path = require('path')
const FormData = require('form-data')
const express = require('express')
const fetch = require('node-fetch')
const router = express.Router()
const multipart = require('connect-multiparty');
var multipartMiddleware = multipart()
router.post('/uploadFile', multipartMiddleware,  (req, res) => {
  const { path: filePath, originalFilename } = req.files.file
  const newPath = path.join(path.dirname(filePath), originalFilename) // 獲得newPath新地址用於建立讀取流
  fs.rename(filePath, newPath, (err) => {
    if (err) {
      return;
    } else {
      const file = fs.createReadStream(newPath) //建立讀取流
      const form = new FormData() // new formdata實例
      form.append('file', file) // 把文件加入到formdata實例中
      fetch('後臺接口上傳地址like:https://ip:端口/接口', {
        method: "POST",
        body: form,
        headers: form.getHeaders()  // 這步很是重要必定要把formdata的headers放在請求體headers中我發現網上不少例子講的都沒這個headers,沒有這個後臺仍是會報boundary的錯由於boundary是在request headers中
        }).then(res => res.json()).then(data => {
          res.send({data: data}) //將上傳結果返回給前端
        })
      }
   })
});
複製代碼

這種方式沒有使用node http請求使用到了fetch,只是一種請求方式,換成axios其實也是同樣的,最主要的是發送請求的時候除了往formdata中append file文件信息外,headers必定要是formdata的headers否則後臺仍是接收不到request中的boundary。前端

node http方式發送請求到後臺

const fs = require('fs')
const path = require('path')
const FormData = require('form-data')
const express = require('express')
var http = require('http');
const router = express.Router()
const multipart = require('connect-multiparty');
var multipartMiddleware = multipart()
router.post('/uploadFile', multipartMiddleware,  (req, res) => {
  const { path: filePath, originalFilename } = req.files.file
  const newPath = path.join(path.dirname(filePath), originalFilename) // 獲得newPath新地址用於建立讀取流
  fs.rename(filePath, newPath, (err) => {
    if (err) {
      return;
    } else {
      const file = fs.createReadStream(newPath) //建立讀取流
      const form = new FormData() // new formdata實例
      form.append('file', file) // 把文件加入到formdata實例中
      var request = http.request({
          method: 'post',
          host: 'http://ip:port',
          path: '/xxxx', //上傳接口
          headers: form.getHeaders()  //formdata的headers
      });
      form.pipe(request);
      request.on('response', (response) => {
        res.send({data: response})
      });
    }
  })
})
複製代碼

這種方式使用的是node中http方式,相關注意事項其實跟node-fetch差很少只是發送的差異而已。vue

其實項目中咱們是把請求方式http單獨抽取到一個文件中的這樣方便管理,這裏只是爲了方便說明狀況把它放到node中臺接口中。其實無論是哪一種方式都是換湯不換藥的都是將append後formdata中的文件信息同時還有formdata headers發送到後臺接口就能夠了。

今天週末有時間總結一下,最後若是有不對的地方但願你們指正一塊兒學習,謝謝!java

相關文章
相關標籤/搜索