在node js中使用FormData多部分post请求上传文件



我不明白这个用例有什么问题。如果请求的文件主体被直接传递给form-data http上传不起作用,但如果写入文件,然后传递文件流读取器到form-data请求工作。

测试客户端

import fs from "fs";
import FormData from "form-data";
import ky from "ky-universal";
const main = async () => {
const { body } = await ky.get(
"https://file-examples-com.github.io/uploads/2017/10/file-sample_150kB.pdf"
);
const form = new FormData();
// This works
const writeStream = fs.createWriteStream("./tmp.pdf");
body.pipe(writeStream);
const fileStream = fs.createReadStream("./tmp.pdf");
form.append("file", fileStream);
// This doesn't work
// form.append("file", body);
form.append("param", "param value");
const res = await ky.post(`http://localhost:3030/upload`, {
timeout: 20000,
body: form,
});
const json = await res.json();
console.log(json);
};

测试服务器

// mkdir uploads
// npm install express multer
import express from "express";
import multer from "multer";
var upload = multer({ dest: "uploads/" });
var app = express();
app.post(
"/upload",
upload.single("file"),
function (req, res, next) {
console.dir(req.file);
console.dir(req.body);
res.json({ ok: true });
}
);
app.listen(process.env.PORT || 3030);

https://gist.github.com/davidnussio/8148b2296a476637bb7e4dae8cf52d44

<标题>

更新解决方案

可能与此问题有关,可能与我使用节点PassThrough流有关,但作为变通方法,而是将响应直接插入表单数据到post请求,我将流消耗到新的缓冲区变量。

async function client() {
const { body } = await ky.get(
"https://file-examples-com.github.io/uploads/2017/10/file-sample_150kB.pdf"
);
return new Promise((resolve, reject) => {
const data = [];
const writableStream = new stream.Writable({
defaultEncoding: "utf-8",
});
writableStream._write = (chunk, encoding, next) => {
data.push(Buffer.from(chunk, encoding));
next();
};
stream.pipeline(body, writableStream, (err) => {
if (err) {
return reject(err);
}
const form = new FormData();
const buffer = Buffer.concat(data);
form.append("file", buffer, { filename: 'tmp.pdf' });
form.append("param", "param-value");
ky.post(url1, {
timeout: 20000,
body: form,
})
.json()
.then((json) => resolve(json))
.catch((error) => reject(error.message));
});
});
}

要上传文件,您需要在标题中发送正确的内容类型("multipart/form-data")。FormData为你准备了头文件,你可以通过form.getHeaders()获得这个头文件。

最新更新