英文:
How to convert files in Formidable Incomming form to base64
问题
我正在构建一个next
js项目,基本上它从客户端(表单)获取数据,通过HTTP请求(axios
)将数据发送到服务器,然后使用xmlrpc
将数据发送到odoo
erp。问题是表单中有文件,我想要做的是直接将数据和文件发送到odoo,而不将它们存储在我的服务器上,注意odoo只接受base64编码
的文件。
这是我的前端代码
const SubmitHandeler = (values) => {
const formdata = new FormData();
formdata.append('nom', values.nom);
formdata.append('prenom', values.prenom);
formdata.append('email', values.email);
formdata.append('phone', values.phone);
values.files.forEach((file) => {
formdata.append(`file`, file);
});
setUploading(true);
axios.post("/api/upload", formdata, {
onUploadProgress: (progressEvent) => {
const progressPercent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
setProgress(progressPercent);
},
}).then((result) => {
setUploading(false);
// router.push('/');
console.log(result.data);
}).catch((err) => {
setUploading(false);
console.log(err)
});
}
对于我的后端代码,我使用了formidable
来解析请求,如您下面所见,在formidable.IncomingForm constructor
中的编码选项中,如果我指定格式为base64
,则解析的文件数组将为空(不知道为什么),但如果我不指定编码,文件数组会得到一些实际的文件,我可以存储并且可以正常使用,但无法将它们转换为base64,尽管在formidable中的文件(类型:formidable.File)
具有.toString()
方法,但它不允许您指定编码(例如在fs中我们可以这样做file.toString("base64")
),但在formidable中我们不能。
export default async function handeler(req, res) {
const form = new formidable.IncomingForm({ multiples: true, encoding: "base64" });
const formData = new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject("error");
}
resolve({ fields, files });
});
});
const { fields, files } = await formData;
//SEND TO ODOO
send_data_to_odoo(/*args*/)
res.status(200).json({ msg: "done" })
}
- 我尝试过multer:不适合我,因为multer会将文件存储在fs中,我不希望这样
- 我尝试了在前端使用
js const base64String = Buffer.from(fileData).toString('base64');
将其转换为base64,但没成功 - 我尝试使用
file.toString()
希望odoo能接受,但没有成功
英文:
im building a next
js project, basically it gets data from the client (form) and send it to the server through http request (axios)
and then use xmlrpc
to send it to odoo
erp
the thing is that the form has files on it, what i want to do is send data and the files directly to odoo without storing them in my server, nota that odoo accepts only files with base64 encoding
,
here is my frontend code
const SubmitHandeler = (values) => {
const formdata = new FormData();
formdata.append('nom', values.nom);
formdata.append('prenom', values.prenom);
formdata.append('email', values.email);
formdata.append('phone', values.phone);
values.files.forEach((file) => {
formdata.append(`file`, file);
});
setUploading(true);
axios.post("/api/upload", formdata, {
onUploadProgress: (progressEvent) => {
const progressPercent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
setProgress(progressPercent);
},
}).then((result) => {
setUploading(false);
// router.push('/');
console.log(result.data);
}).catch((err) => {
setUploading(false);
console.log(err)
});
}
for my backend code, ive used formidable
to parse the request, as u can see next, in the encoding option in the formidable.IncomingForm constructor
, if i specify the format to base64
, the resolved array of files will be empty (dont know why) but if i dont specify the encoding, the array of files got some actual files that i can store and i can work with them normally, but cant convert them into base64 although files in formidable (type : formidable.File)
has a .toString()
method but it doesnt let u specify the encoding (in fs for example we can do file.toString("base64")
), but in formidable we cant
export default async function handeler(req, res) {
const form = new formidable.IncomingForm({ multiples: true, encoding: "base64" });
const formData = new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject("error");
}
resolve({ fields, files });
});
});
const { fields, files } = await formData;
//SEND TO ODOO
send_data_to_odoo(/*args*/)
res.status(200).json({ msg: "done" })
}
- ive tried multer : dont suit me since multer stores files on the fs and i dont want that
- ive tried converting to base64 both in the frontend using
js const base64String = Buffer.from(fileData).toString('base64');
but that didnt work - ive tried to use
file.toString()
hoping odoo accepts it but no
答案1
得分: 1
你可以使用 btoa 来将字符串转换为 base64 格式,使用 atob 来解码 base64 格式的字符串。
在你的 Next.js 应用程序(前端部分)中,看起来你没有将文件编码为 base64 格式,因此在你的 API 端点上不需要使用 encoding: "base64"
。因此,你应该在后端进行编码。
export default async function handler(req, res) {
// 你不需要将文件转换
const form = new formidable.IncomingForm({ multiples: true });
const formData = new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject("error");
}
resolve({ fields, files });
});
});
const { fields, files } = await formData;
// 你将每个文件转换为 base64 格式
for (const file in files) {
files[file] = btoa(files[file]);
}
// 发送到 Odoo
send_data_to_odoo(/*参数*/)
res.status(200).json({ msg: "完成" })
}
你还可以验证文件是否已经以 base64 格式编码,使用以下代码:
let isBase64 = false;
try {
// 如果你可以从 base64 格式转换文件,那么文件已经编码了
atob(files[file]);
isBase64 = true;
} catch (err) {
console.log('已经是 base64 格式');
}
英文:
You can use btoa to convert to the base64 format a string, and atob to decode a string from the base64 format.
In your next.js app (the frontend part), it looks like you aren't encoding the file to the base64 format, so you don't need to use encoding: "base64"
on your api endpoint. Thus you should encode it on the backend.
export default async function handeler(req, res) {
// you don't need to convert the files
const form = new formidable.IncomingForm({ multiples: true });
const formData = new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject("error");
}
resolve({ fields, files });
});
});
const { fields, files } = await formData;
// you convert each file to base64 format
for (const file in files) {
files[file] = btoa(files[file]);
}
//SEND TO ODOO
send_data_to_odoo(/*args*/)
res.status(200).json({ msg: "done" })
}
You can also verify that the file is not already encoded in base64 format with
let isBase64 = false;
try {
// if you can convert the file from the base64 format, then the file is already encoded
atob(files[file]);
isBase64 = true;
} catch (err) {
console.log('Already base64 format');
}
答案2
得分: 0
你可以读取文件,然后使用Buffer的toString()
方法,将"base64"
作为参数传递。
尝试这样做:
const formData = new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject("error");
}
Object.values(files).forEach((file) => {
const buffer = fs.readFileSync(file.filepath);
const base64 = buffer.toString("base64");
console.log("File base64", base64.slice(0, 10));
});
});
});
英文:
You can read the file and then use the Buffer toString()
method passing "base64"
as param.
Try this:
const formData = new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
reject("error");
}
Object.values(files).forEach((file) => {
const buffer = fs.readFileSync(file.filepath);
const base64 = buffer.toString("base64");
console.log("File base64", base64.slice(0, 10));
});
});
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论