我创建了一个
FormData
,如下(简化):
import FormData from 'form-data';
const createForm = async () => {
const form = new FormData();
form.append('field1', 'stringValue1');
form.append('fileField', fs.createReadStream(__filename), {
contentType: 'text/javascript',
filename: 'file.js',
});
return form;
};
然后通过 HTTP/2(明文)发送:
// app is a FastifyInstance
await app.ready();
const { address, port } = app.server.address();
const client = http2.connect(`http://${address}:${port}`);
const request = client.request({
':method': 'POST',
':path': '/path',
'content-type': `multipart/form-data; boundary=${form.getBoundary()}`,
});
request.setEncoding('utf8');
let status;
request.on('response', (headers) => {
status = headers[':status'];
});
request.on('data', (data) => { ... });
form.pipe(request);
request.end();
await new Promise((resolve) => {
request.on('end', () => {
client.close();
resolve();
});
});
然后在 Fastify 服务器中监听我的请求
import fastify from 'fastify';
import fastifyFormbody from '@fastify/formbody';
import fastifyMultipart from '@fastify/multipart';
const app = fastify({ http2: true, logger: logLevel === 'debug' });
const fieldSizeLimit = 1024 * 1024 * 10;
void app.register(fastifyFormbody);
void app.register(fastifyMultipart, {
attachFieldsToBody: 'keyValues',
limits: {
fieldSize: fieldSizeLimit,
fileSize: fieldSizeLimit,
},
onFile: async (part) => {
const destinationPath = path.join(bundlePath, 'uploads', part.filename);
await saveMultipartFile(part, destinationPath);
// eslint-disable-next-line no-param-reassign
part.value = {
filename: part.filename,
savedFilePath: destinationPath,
type: 'asset',
};
},
});
app.post('/path', async (req, res) => {
console.log(Object.entries(req.body));
...
});
它可以很好地处理 HTTP/1.1 请求。并且日志显示未收到
fileField
。如何正确提出请求?
我发现打开http/2连接并发布表单数据,上面写着
在 Node HTTP2 文档中,它展示了如何执行此操作的示例。
但似乎只是在谈论分离
const client = http2.connect(...)
和client.request
,而不是表单数据示例。
我需要支持的最低 Node 版本是 20,如果需要的话我很乐意从
form-data
切换;我只是在内置 FormData
时遇到了不同的错误,但也许我在那里做错了什么。
解决办法是更换
form.pipe(request);
request.end();
与
form.pipe(request);
form.on('end', () => { request.end(); });