公司几个项目都是三层架构模式即前台,中台(中间层),后台。前台微信端公众号使用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
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。前端
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
今天周末有时间总结一下,最后若是有不对的地方但愿你们指正一块儿学习,谢谢!java