express使用 formidable 处理文件上传时form.parse(),form.on(‘fileBegin‘),form.on(‘file‘)他们之间的作用和位置

  1. form.parse()
    form.parse() 是 formidable 的核心方法,用于解析传入的 multipart/form-data 请求(通常是文件上传请求)。它会自动处理文件的接收、保存等操作,并触发相关的事件。
    作用:解析请求体,处理文件和字段数据。
    位置:这是文件上传的主要入口点。
const formidable = require('formidable');

app.post('/upload', (req, res) => {
    const form = new formidable.IncomingForm();
    form.parse(req, (err, fields, files) => {
        if (err) {
            return res.status(500).send('文件上传失败');
        }
        console.log('接收到的文件:', files);
        res.send('文件上传成功');
    });
});
  1. form.on(‘fileBegin’)
    fileBegin 事件在文件开始上传时触发。你可以在这个事件中设置文件的保存路径、文件名等。
    作用:在文件开始上传时进行预处理,例如修改文件名或保存路径。
    位置:在文件上传之前。
const formidable = require('formidable');
const path = require('path');

app.post('/upload', (req, res) => {
    const form = new formidable.IncomingForm();

    form.on('fileBegin', (name, file) => {
        // 修改文件名和保存路径
        const ext = path.extname(file.name);
        const newFileName = `${Date.now()}${ext}`;
        file.path = path.join(__dirname, 'uploads', newFileName);
    });

    form.parse(req, (err, fields, files) => {
        if (err) {
            return res.status(500).send('文件上传失败');
        }
        console.log('文件已保存:', files);
        res.send('文件上传成功');
    });
});
  1. form.on(‘file’)
    file 事件在文件上传完成时触发。你可以在这个事件中获取文件的详细信息,例如文件路径、大小等。
    作用:在文件上传完成后进行处理,例如记录日志或进行后续操作。
    位置:在文件上传完成后。
const formidable = require('formidable');
const path = require('path');

app.post('/upload', (req, res) => {
    const form = new formidable.IncomingForm();

    form.on('fileBegin', (name, file) => {
        const ext = path.extname(file.name);
        const newFileName = `${Date.now()}${ext}`;
        file.path = path.join(__dirname, 'uploads', newFileName);
    });

    form.on('file', (name, file) => {
        console.log('文件已保存:', file);
    });

    form.parse(req, (err, fields, files) => {
        if (err) {
            return res.status(500).send('文件上传失败');
        }
        res.send('文件上传成功');
    });
});

总结

  • 文件上传的主要实现:在 form.parse() 方法中完成。
  • 文件路径和文件名的预处理:在 fileBegin 事件中完成。
  • 文件上传完成后的处理:在 file 事件中完成。
  • 最终结果处理:在 form.parse() 的回调函数中完成。

这里给一个完整上传图片,并判断是否图片,以及重新生成图片避免恶意代码

app.post('/upload', (req, res) => {
    const form = new formidable.IncomingForm();

    const uploadDir = path.join(__dirname, 'public', 'uploads');
    if (!fs.existsSync(uploadDir)) {
        fs.mkdirSync(uploadDir, { recursive: true });
    }

    form.on('fileBegin', (name, file) => {
        console.log(`File upload started: ${name}`);
        const ext = path.extname(file.originalFilename);
        const new_file_name = `${Date.now()}${ext}`;
        file.path = path.join(uploadDir, new_file_name); // 设置目标路径

    });

    form.parse(req, async (err, fields, files) => {
        if (err) {
            console.error('Formidable parse error:', err);
            return res.status(500).send('文件上传失败');
        }

        console.log('接收到的文件:', files);

        if (!files.photo || !Array.isArray(files.photo) || files.photo.length === 0) {
            console.error('未接收到文件或文件数组为空');
            return res.status(400).send('未接收到文件');
        }

        const file = files.photo[0]; // files.photo 是一个数组
        const tempPath = file.filepath; // 临时路径
        const targetPath = file.path; // 目标路径

        if(!file.mimetype.startsWith('image/'))
        {
            console.error('上传的文件不是图片');
            fs.unlink(tempPath,()=>{});
            return res.status(400).send('只允许上传图片');
        }

        console.log(`Copying file from ${tempPath} to ${targetPath}`);

        // 使用 sharp重新生成图片
        try{
            await sharp(tempPath)
            .toFormat('png')
            .toFile(targetPath);
            console.log(`图片已经处理和保存在:${targetPath}`);
            
            //删除临时文件
            fs.unlink(tempPath,(unlinkErr)=>{
                if(unlinkErr)
                {
                    console.error('删除临时图片失败:',unlinkErr);
                }
            });

			//这里是生成获取表单的值及上传的图片的相对路径,然后存入数据库,先写在对象中再存入
            const dataToSave={
                name:fields.name[0],
                email:fields.email[0],
                photoPath:path.relative(__dirname,targetPath)   //获取相对目录的图片路径
            };

            console.log('数据对象:',dataToSave);
            res.send('文件上传成功');
        }catch(sharpErr)
        {
            console.log('图片处理失败:',sharpErr);
            res.status(500).send('图片处理失败,请上传正确的图片');
        }
        
    });

    form.on('error', (err) => {
        console.error('Formidable 错误:', err);
        res.status(500).send('文件上传失败');
    });
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值