如何解决使用 NodeJS 和 node-fetch 代理多部分表单数据
如何将传入的 NodeJS/Express 请求 (req) 对象转换为可以在代理请求中发送的对象?
我的 NodeJS/express 服务使用 node-fetch 将请求代理到单独的服务器。传入的 curl 请求如下所示(Firefox POSIX curl)
curl 'https://localhost:8080/bluecost/spreadsheet/upload/SSCSpreadsheetUpload-09192020.xlsx' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0' -H 'Accept: application/json,text/plain,*/*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Content-Type: multipart/form-data; boundary=---------------------------37552304939101372432093632492' -H 'Origin: https://localhost:8080' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: https://localhost:8080/spreadsheet-upload' -H 'Cookie: connect.sid=s%3ARxnRck1VzcCXk05LKV1CJ5PeslCK1sWC.WqqK%2B0CHsAP0MpcFzRFbHTh19YOoeBi0mIAKCPQ%2BSGU; access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzcHJpbnQtbWlkZGxld2FyZS1pc3N1ZXIiLCJzdWIiOiJCZW4uUHJhY2h0MUBpYm0uY29tIiwibm90ZXNJZCI6IkJlbiBQcmFjaHQiLCJzZXJpYWxOdW0iOiI4Njc1NTU4OTciLCJleHAiOjE2MTQ4MjgwNzksImJsdWVHcm91cHMiOlsiQkxVRUNPU1RfU1BSRUFEU0hFRVRfVVBMT0FEX1RFU1QiXSwiaWF0IjoxNjE0ODIwODk3fQ.jWhvsHZiJLRvAHG7SDTmOkdcpMRHxiaLUWDhfJmRXv0' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' --data-binary $'-----------------------------37552304939101372432093632492\r\nContent-Disposition: form-data; name="file"; filename="SSCSpreadsheetUpload-09192020.xlsx"\r\nContent-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\r\n\r\n-----------------------------37552304939101372432093632492--\r\n'
路由的简化版本如下所示:
app.use('/multipart',(req,res,next) => {
const URL = require('url').URL;
var spreadsheet_client_url = new URL(config.spreadsheet_client_host);
spreadsheet_client_url.pathname = req.originalUrl;
// spreadsheet_client_url.pathname = spreadsheet_client_url.pathname.replace('/spreadsheet-upload','/');
logger.debug('/spreadsheet-upload: Generating token based on proxyReqOpts.user=' + req.user);
logger.info(`@@Request ${req.method} ${spreadsheet_client_url.href}`);
var accessToken = generateToken(req.user);
/**
* Set bearer token based on code from Sprint-API's lua code
*/
// req.setHeader('Authorization','Bearer ' + accessToken);
logger.debug('Route: /spreadsheet-upload: adding Authorization: Bearer ' + accessToken);
var newHeaders = req.headers;
newHeaders['Authorization'] = 'Bearer ' + accessToken;
if (isMultipartRequest(req)) {
newHeaders['Content-Length'] = req.body.length;
// build a string in multipart/form-data format with the data you need
const formdataUser =
`--${request.headers['content-type'].replace(/^.*boundary=(.*)$/,'$1')}\r\n` +
`Content-Disposition: form-data; name="reqUser"\r\n` +
`\r\n` +
`${JSON.stringify(req.user)}\r\n`
} else {
const options = {
port: spreadsheet_client_url.port,path: spreadsheet_client_url.pathname,body: req.body,method: req.method,headers: newHeaders,redirect: true
};
console.log('@@@');
console.log('@@@ url: ' + spreadsheet_client_url.href + 'post-options: ' + JSON.stringify(options));
console.log('@@@');
const fetch = require('node-fetch');
fetch(spreadsheet_client_url,options).then(r => {
console.log('@@ reached fetch result retrieved');
return r.text();
}).then(fetchText => {
console.log('@@ reached fetch text result retrieved');
/*
// This code complains that headders can't be set after sending to client
res.writeHead(res.statusCode,res.headers);
res.send(fetchText);
*/
// res.body=fetchText;
res.status(200).send(fetchText);
next();
}
}
)
.catch(err => { console.log('Error fetching ' + err) });
})
function isMultipartRequest(req) {
let contentTypeHeader = req.headers['content-type'];
return contentTypeHeader && contentTypeHeader.indexOf('multipart') > -1;
}
所以我有一个传入请求,我相信我可以可靠地区分普通请求和多部分请求。许多例子建议创建这个“表单数据”对象,然后像这样发送它:
const FormData = require('form-data');
const form = new FormData();
const buffer = // e.g. `fs.readFileSync('./fileLocation');
const fileName = 'test.txt';
form.append('file',buffer,{
contentType: 'text/plain',name: 'file',filename: fileName,});
fetch('https://httpbin.org/post',{ method: 'POST',body: form })
.then(res => res.json())
.then(json => console.log(json));
我想继续使用 node-fetch 因为它是我最了解的魔鬼。我应该使用表单数据对象并像上面一样传递它吗?有没有更好的办法?我想知道如何从请求对象构建表单数据对象,因为我只知道它是多部分的,仅此而已。
最终目标是一个 Java Spring-Boot 服务器,它接受一个 MultipartFile 文件,如下所示:
@PostMapping("/spreadsheet/upload/{filename}")
public ResponseEntity<HashMap<String,Object>> uploadSpreadsheet(@RequestBody MultipartFile file,@PathVariable("filename") String filename) {
对于普通的非多部分表单请求,它足以匹配到此方法,但“文件”对象为空。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。