Frankie
Frankie

Reputation: 195

Node.js file picture upload only if extension is correct with formidable

I would like to upload a picture on my Node.js server only if the picture is a real png / jpeg / jpg / gif file.

For testing purpose, I have 2 files : a "fake" png (a pdf file whose extension has been manually modified) and a real one.

I use formidable library for this. I have two functions. Neither function works as expected : actually, I would like the file to be written on the server disk only if the type is correct.

router.post('/producer', (req, res, next) => {
    uploadImage1(req, res, next);
    //uploadImage2(req, res, next);
    ...
});

Function 1 :

function uploadImage1(req, res, next) {
    const formidableOptions = {
        multiples: false,
        keepExtensions: true,
        uploadDir: __dirname + '/pictures',
        maxFileSize: MAX_SIZE_FILE_UPLOAD_KO * 1024
    }
    const form = formidable(formidableOptions);

    form.parse(req, async (err, fields, files) => {
        if (err) {
            return res.status(400).json("Something went wrong with your request");
        }
        const buffer = readChunk.sync(files.fileToUpload.path, 0, 4100);
        const fileType = await FileType.fromBuffer(buffer);

        if(!fileType.ext.match(/(jpg|jpeg|png|gif)$/i)) {
            return res.status(400).json("Upload file type error");  
        }      
        return res.status(200).json("Image correctly uploaded");
    });
}

My servers responses :

But, in both cases, the file is written on my server disk, whereas logically it shouldn't for the wrong file type.

Function 2 :

function uploadImage2(req, res, next) {
    const formidableOptions = {
        multiples: false,
        keepExtensions: true,
        uploadDir: __dirname + '/pictures',
        maxFileSize: MAX_SIZE_FILE_UPLOAD_KO * 1024
    }
    const form = formidable(formidableOptions);

    form.parse(req);

    form.onPart = (part) => {
        part.on('data', async (buffer) => {
            const fileType = await FileType.fromBuffer(buffer);
            if (fileType) {
                if (!fileType.ext.match(/(jpg|jpeg|png|gif)$/i)) {
                    return res.status(400).json("Upload file type error");
                } else {
                    // What to do next ? The picture is not written to server directory...
                    return res.status(200).json("Image correctly uploaded");
                }
            }
        });
    };
}

My servers responses :

But, in both cases, the file is never written on my server disk, whereas logically it should be in the correct case...

I'm stuck with this. Do you know how I could fix this please ? Many thanks.

Upvotes: 0

Views: 742

Answers (1)

Walle Cyril
Walle Cyril

Reputation: 3247

Inside Function 1 : you are reading the file from disk with readChunksync. It means the file is already there. You need to remove it after res.status(400).json("Upload file type error"); with fs.unlink for example.

Inisde form.parse callback the files are already written.

Another way to do this is to pass in a custom options.fileWriteStreamHandler which checks for the type.

Upvotes: 0

Related Questions