如何在 NodeJS 中将多部分请求从一台服务器传递到另一台服务器?

问题描述 投票:0回答:3

我有两个nodeJS服务器, 服务器 1 获取来自客户端的请求,并将其传递给服务器 2,服务器 2 将响应返回给服务器 1,服务器 1 响应客户端。 客户端上传一个文件,它必须以与我拥有的任何其他休息请求相同的方式传递。

我在服务器 1 上使用 axios 将数据发送到服务器 2,并在服务器 2 上使用 multer 将文件存储在磁盘上。

我在将请求从 server1 发送到 server2 时遇到问题,因为请求正文不包含任何内容,并且请求是 Multipart

我应该如何处理服务器1上的请求???

router.post('/fileUpload', (req, res) => {
    console.log(req.body);
    res.status(200).json({ msg: "Got file" });
});
node.js axios multipartform-data multer
3个回答
25
投票

您可以使用

form-data
模块从nodejs应用程序发送多部分/表单数据

这是您可以在 Server1 上实现的代码,用于从客户端接收图像文件并将其发送到 Server2。

const express = require("express");
const app = express();
const bodyParser = require('body-parser');
var multer  = require('multer')();
const FormData = require('form-data');
const axios = require('axios');
const fs = require('fs');

app.use(bodyParser.json());

app.post('/fileUpload' , multer.single('fileFieldName'), (req , res) => {
    const fileRecievedFromClient = req.file; //File Object sent in 'fileFieldName' field in multipart/form-data
    console.log(req.file)

    let form = new FormData();
    form.append('fileFieldName', fileRecievedFromClient.buffer, fileRecievedFromClient.originalname);

    axios.post('http://server2url/fileUploadToServer2', form, {
            headers: {
                'Content-Type': `multipart/form-data; boundary=${form._boundary}`
            }
        }).then((responseFromServer2) => {
            res.send("SUCCESS")
        }).catch((err) => {
            res.send("ERROR")
        })
})

const server = app.listen(3000, function () {
    console.log('Server listening on port 3000');
});

这里

multer
用来处理上传的文件


1
投票
 const formData = new FormData();
 formData.append('query', updateDocQuery);
 formData.append('variables', JSON.stringify(this.setUpdateDocParams() || {}));
 for (let i = 0; i < fileArr.length; i++) {
            formData.append(`file${i}`, fileArr[i])
        }

您可以将查询变量和文件附加到 formData 并将 formData 传递到 body


0
投票

为了完成 Apar Adhikari 的回答,我还意识到我需要什么来实现这个端到端的过程:

html表单文件输入->onsubmit事件->客户端post文件到svr 1->svr 1中的文件->svr 2中的文件

也在服务器 1 上使用 fs.createReadStream(filepath)

读取
文件服务器端,其中
filepath
是我选择将文件上传到的相对文件路径 - 目前使用 Multer 在磁盘上。

仅在此文件读取步骤之后,我将

fs.createReadStream(filepath)
作为他称为
form
的 formData 对象中的值附加到我位于服务器 2 上的第 3 方 API 将识别的密钥。

所以,基本上,这是我的文件所经历的旅程,一旦

onsubmit
事件在客户端触发,并且文件从客户端发布到服务器 1

require("dotenv").config()
const express = require("express")
const bodyParser = require('body-parser')
const FormData = require('form-data') // svr-side require for multipart/form-data encoding
const path = require('path')
const fs = require('fs') // required to call fs.createReadStream() - see below
const cors = require('cors')
const multer  = require('multer')
const axios = require('axios') // svr-side require for req to 3rd-party API


// Multer file storage options - I chose to store the file on DISK with the help of Multer, in a ./uploadFiles directory
const uploadedFilesFolderName = "uploadFiles"
const UPLOAD_DIR = `${__dirname}/${uploadedFilesFolderName}`
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, UPLOAD_DIR);
  },
  filename: function (req, file, cb) {
    cb(null, `${file.originalname}`);
  },
})
const upload = multer({ storage: storage });

const app = express()
const PORT = // port of your choice here
//const PORT = process.env.PORT // to change used PORT
const API_URL = "https://my.apiurl.com/"

app.use(express.static("public"))
app.use(express.json())
app.use(bodyParser.json())
app.use(cors())
app.use(express.static(UPLOAD_DIR)) // my ./uploadFiles dir

// serving index.html where the file input form is
app.get("/", function (request, response) {
  response.sendFile(__dirname + "/public/views/index.html")
})

// my client->svr 1 post route
// in my HTML, the name of the file input field is 'fileInput'
// retrieved here with the help of upload.single('fileInput') arg
app.post('/upload-single-file', upload.single('fileInput'), async function (req, res, next) {
  try {

    // retrieving also text fields from the HTML form
    // (eg a file description, an option chosen by user via a drop-down...)
    const whateverTxt = req.body.whateverField // see multer doc for details on req.body

    const fileFromClient = req.file // see multer doc for details on req.file object
    
    //...

    const apiToken = // here the result of a login request or sth authenticating into my 3rd-party API
    // do whatever other prior async/await request with axios here

    //...
    
    // 1. Build the filepath where the file retrieved from client-side has "landed" (my ./uploadFiles dir)
    let uploadedFilePath = `./${uploadedFilesFolderName}/${fileFromClient.originalname}`

    // 2a. In this server 1, read the contents of the file to upload to server 2
    // with fs.createReadStream(uploadedFilePath)
    // 2b. Append fs.createReadStream(uploadedFilePath) into a new FormData object key-value pair
    // with appropriate field for API on server 2
    let form = new FormData();
    form.append('fieldWhereToSendFileTo', fs.createReadStream(uploadedFilePath))

    
    const API_POST_FILE_ENDPOINT = API_URL + `whatever/endpoint/to/post/to`

    // using Apar Adhikari's answer
    const fileResp = await axios.post(API_POST_FILE_ENDPOINT, form, {
        headers: {
          "id": apiToken,
          "Content-Type": `multipart/form-data; boundary=${form._boundary}`
        }
      })
    //console logging info received from svr 2 into svr 1
    console.log(`POST/File to API - Status ${fileResp.status} - headers: ----${fileResp.headers}`) 
    

    // sending some response from svr 1 back to the client - including info from svr 2 axios response above (svr 2 -> svr 1 -> client)
    res.json({ message: "successful file upload!", 
    data: req.file,
    someOtherField: someOtherValue
    postFileStatus: fileResp.status,
    postFileHeaders: fileResp.headers,
    url: `http://localhost:${PORT}/${req.file.originalname}`})

  } catch (error) {
    res.json({ message: "error - ", error })
  }

})

// listen for requests :)
const listener = app.listen(PORT, function () {
  console.log("Express SVR - Your app is listening on port " + listener.address().port)
})

希望这个解释有帮助

© www.soinside.com 2019 - 2024. All rights reserved.