NodeJS 如何将Formidable Incoming格式的文件转换为base64

bfhwhh0e  于 2023-06-22  发布在  Node.js
关注(0)|答案(2)|浏览(201)

我正在构建一个next js项目,基本上它从客户端获取数据(表单)然后通过http请求(axios)发送到服务器然后用xmlrpc发送到odoo erp问题是表单上有文件,我想做的是把数据和文件直接发送到odoo而不存储在我的服务器里,注意odoo只接受带有base64 encoding的文件,这里是我的前端代码

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,虽然在强大的(type : formidable.File)中的文件有一个.toString()方法,但它不允许你指定编码(例如在fs中,我们可以做file.toString("base64")),但在强大的我们不能。

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接受它,但没有
pnwntuvh

pnwntuvh1#

可以使用btoa将字符串转换为base64格式,使用atob将字符串从base64格式解码。
在你的next.js应用程序(前端部分)中,看起来你没有将文件编码为base64格式,所以你不需要在你的API端点上使用encoding: "base64"。因此,您应该在后端对其进行编码。

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" })
}

您还可以使用以下命令验证文件是否已编码为base64格式:

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');
}
1bqhqjot

1bqhqjot2#

您可以读取该文件,然后使用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));
    });
    
  });
});

相关问题