Several projects of the company are based on a three-tier architecture mode, namely front desk, middle stage (middle layer) and back office. The foreground wechat public account uses vUE framework, the foreground management uses React, the middle stage (middle layer) uses Node, and the background uses Java. Because it is a three-tier architecture, the foreground form will first be submitted to the node middle layer, and then forwarded to the Java background through the Node middle layer to save and read the file data. When the form is submitted to the middle layer of Node, the Node interface Request can obtain the file information uploaded to the form. When the node creates the HTTP request and forwards it to the background, the background reports an error: The request was rejected because no multipart boundary was found The content-type of headers in the HTTP request created by Node is multipart/form-data. It is clear that the Java background does not receive the upload file information, and the background can upload the file by creating the form form on the page using the address of the background upload interface. This proves that the backend interface is ok, and the node central interface can also receive the form upload file data, then further narrow the problem appears in the Node HTTP request forward to the backend. Since there was no boundary in the request body of background interface, the problem occurred when the request was created, the background was short of things. Google+ Baidu found a solution, but it was not found to be completely useless, but the direction was still found. The backend requires form data, so node forwards a form data when forwarding it. So we found the form-data package and the connect-Multiparty middleware. Insert a piece of code and then analyze it;

Node-fetch sends requests to the background

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) // Get the newPath address to create the read stream
  fs.rename(filePath, newPath, (err) => {
    if (err) {
      return;
    } else {
      const file = fs.createReadStream(newPath) // Create a read stream
      const form = new FormData() // New formData instance
      form.append('file', file) // Add file to formData instance
      fetch('Background interface upload address like: https://ip: port/interface', {
        method: "POST".body: form,
        headers: form.getHeaders()  // This step is very important to make sure that the headers of formData are placed in the headers of the request body. I have found that many examples on the web do not have this headers
        }).then(res= > res.json()).then(data= > {
          res.send({data: data}) // Returns the upload result to the front-end})}})});Copy the code

In this way, fetch is not used for node HTTP request, which is just a request method. In fact, it is the same for AXIOS. The most important thing is that when sending a request, besides the information of append file in formData, Headers must be headers of formData, or the background still cannot receive the request boundary.

Node sends HTTP requests to the background

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) // Get the newPath address to create the read stream
  fs.rename(filePath, newPath, (err) => {
    if (err) {
      return;
    } else {
      const file = fs.createReadStream(newPath) // Create a read stream
      const form = new FormData() // New formData instance
      form.append('file', file) // Add file to formData instance
      var request = http.request({
          method: 'post'.host: 'http://ip:port'.path: '/xxxx'.// Upload interface
          headers: form.getHeaders()  / / formdata headers
      });
      form.pipe(request);
      request.on('response', (response) => {
        res.send({data: response}) }); }})})Copy the code

This method uses the NODE HTTP method, and the related considerations are similar to node-fetch, just the difference between sending.

In the project, we actually extracted the request method HTTP into a file to make it easier to manage, but we just put it in the node center interface for the sake of illustration. Either way, it’s the same thing as sending the file information in the append formData and the FormData Headers to the background interface.

I have time to summarize this weekend, and I hope you can correct and study together if there is anything wrong. Thank you!