NodeJS 应用程序不上传文件

NodeJS application doesn't upload files

我正在使用 NodeJS 开发一个非常简单的 JavaScript 应用程序。只需上传文件并按段落查看其内容。

问题是每次我上传文件时,我都会收到“没有上传文件”的错误消息。对应于以下几行:

app.post('/upload_file', (req, res) => {
     if (!req.files || !req.files.filetoupload) {
         return res.status(400).send('No files were uploaded.');
     }
     
     [...]
}

这是完整的代码:

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

if (!fs.existsSync('./db')) {
    fs.mkdirSync('./db');
}
if (!fs.existsSync('./uploads')) {
    fs.mkdirSync('./uploads');
}
let db = new sqlite3.Database('./db/paragraphs.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
    if (err) {
        console.error(err.message);
    }
    console.log('Connected to the paragraphs database.');
});

db.run('CREATE TABLE IF NOT EXISTS paragraphs (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT, tag TEXT)', (err) => {
    if (err) {
        console.error(err.message);
    }
    console.log('Created paragraphs table.');
});

app.get('/', (req, res) => {
    res.send('<h1>Hello World!</h1>' +
        '<meta charset="utf-8">' +
        '<a href="/file_uploading">Upload File</a><br>' +
        '<a href="/visualize_paragraphs">Visualize Paragraphs</a><br>' +
        '<a href="/tag_paragraphs">Tag Paragraphs</a>');
});

app.get('/file_uploading', (req, res) => {
    res.send('<h1>File Uploading</h1>' +
        '<meta charset="utf-8">' +
        '<form action="/upload_file" method="post" enctype="multipart/form-data">' +
        '<input type="file" name="filetoupload"><br>' +
        '<input type="submit">' +
        '</form>');
});

app.post('/upload_file', (req, res) => {
    if (!req.files || !req.files.filetoupload) {
        return res.status(400).send('No files were uploaded.');
    }

    let file = req.files.filetoupload;
    let filename = file.name;

    fs.writeFile('./uploads/' + filename, data, (err) => {
        if (err) {
            return console.log(err.message);
        }
        console.log('The file has been saved!');
    });

    file.mv('./uploads/' + filename, (err) => {
        if (err) {
            return res.status(500).send(err);
        }
        res.send('File uploaded!<br>' +
        '<a href="/file_uploading">Upload Another File</a><br>' +
        '<a href="/visualize_paragraphs">Visualize Paragraphs</a><br>' +
        '<a href="/tag_paragraphs">Tag Paragraphs</a>');
    });


    fs.readFile('./uploads/' + filename, {encoding: 'utf-8'}, (err, data) => {
        if (err) {
            return console.log(err.message);
        }
        let lines = data.split('\n');
        for (let i = 0; i < lines.length; i++) {
            db.run('INSERT INTO paragraphs (text) VALUES (?)', [lines[i]], (err) => {
                if (err) {
                    return console.log(err.message);
                }
            });
        }
    });
});

app.get('/visualize_paragraphs', (req, res) => {
    db.all('SELECT * FROM paragraphs', (err, rows) => {
        if (err) {
            throw err;
        }
        rows.forEach((row) => {
            res.write('<h1>Visualize Paragraphs</h1>');
            res.write(row.text + '<br>');
        });
        res.end();
    });
});

app.get('/tag_paragraphs', (req, res) => {
    let paragraph_id = req.query.paragraph_id;
    let tag = req.query.tag;
    if (paragraph_id && tag) {
        db.run('UPDATE paragraphs SET tag = ? WHERE id = ?', [tag, paragraph_id], function (err) {
            if (err) {
                return console.log(err.message);
            }
            console.log(`Row(s) updated: ${this.changes}`);
        });
        res.send('<h1>Tag Paragraphs</h1>' +
            '<p>Paragraph ' + paragraph_id + ' has been tagged as ' + tag + '</p>');
    } else {
        db.all('SELECT * FROM paragraphs', (err, rows) => {
            if (err) {
                throw err;
            }
            res.write('<h1>Tag Paragraphs</h1>' +
                '<table>');
            rows.forEach((row) => {
                res.write('<tr><td>' + row.id + '</td><td>' + row.text + '</td></tr>');
            });
            res.write('</table>' +
                '<form action="/tag_paragraphs" method="get">' +
                '<label for="paragraph_id">Paragraph ID:</label>' +
                '<input type="text" id="paragraph_id" name="paragraph_id"><br>' +
                '<label for="tag">Tag:</label>' +
                '<input type="text" id="tag" name="tag"><br>' +
                '<input type="submit" value="Submit">' +
                '</form>');
            res.end();
        });
    }
});

app.listen(3000, () => {
    console.log('Example app listening on port 3000!');
});

你能帮帮我吗?我做错了什么?

来自the documentation

In Express 4, req.files is no longer available on the req object by default. To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty, or pez.

…而且您没有加载任何此类中间件。

啊,我以前遇到过这个问题

可能是客户端发送的表单类型。

我会调查一下 multer!

https://www.npmjs.com/package/multer

我想你会找到那个包的解决方案

尝试使用 Multer 中间件上传文件,它会让你的生活变得轻松,我附上了我在我的一个项目中使用的示例代码

const express = require('express');
const fs = require('fs');
const Log = require('../utils/Log');
const User = require('../db/models/user_model');
const BandCode = require('../db/models/band_codes')
const UserRouter = new express.Router();
const Response = require('../const/Response');
const auth = require('../middleware/auth');
const path = require('path');
const multer = require('multer')
const sharp = require('sharp')
const appleReceiptVerify = require('node-apple-receipt-verify');
const validator = require('validator');
const { sendPasswordResetEmail } = require('../emails/account');
const { totp } = require('otplib');
const { isError } = require('util');
const key = process.env.TOTP;
totp.options = { step: 1800 }

var storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, process.env.PUBLIC)
    },
    filename: (req, file, cb) => {
        
        cb(null, req.user._id + '' + Date.now() + path.extname(file.originalname))
    }
});


const upload = multer({
    storage,
    limits: {
        fileSize: 9000000
    },
    fileFilter(req, file, cb) {
        if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
            return cb(new Error('Please upload an image'))
        }

        cb(undefined, true)
    }
})

UserRouter.post('/users/avatar', auth, upload.single('avatar'), async (req, res) => {
    console.log("User Image Update Request")
    const filepath = process.env.BASE_PATH  +req.file.filename;
    console.log(filepath)
    req.user.imageUrl = filepath;
    req.user.avatar = null

    // const file = await sharp(req.file.buffer).resize({ width: 250, height: 250 }).png().toFile();
    // req.user.avatar = buffer
    await req.user.save()
    const user = req.user.toObject();
    delete user.avatar
    delete user.password
    delete user.token
    delete user.tokens
    delete user.socialId
    delete user.totop
    delete user.buffer
    delete user.__v
    const response = new Response("SUCCESS", "Image saved", 200, 0, { user });
    res.send(response)
}, (error, req, res, next) => {
    console.log(error);
    res.status(400).send({ error: error.message })
})


module.exports = UserRouter;

您必须使用 multer 进行文件上传

router.post('/upload-file', upload.single('image'))


const multer = require('multer');
const storage = multer.diskStorage({
 destination: function(req, file, cb) {
    cb(null, './uploads');
 },
 filename: function (req, file, cb) {
    cb(null , `${Date.now().toString()}-${file.originalname}`);
 }
});

const upload = multer({ storage: storage, limits: { fieldSize: 10 * 1024 * 1024 } });

从问题中提取的答案,代表提问者添加


这是解决方案和固定代码。

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
const multer = require('multer');
const path = require('path');

// Set up multer
const storage = multer.diskStorage({
    destination: './uploads/',
    filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
    },
});

const upload = multer({
    storage,
    dest: './uploads/',
    limits: {
        fileSize: 1000000
    },
    fileFilter: function (req, file, cb) {
        checkFileType(file, cb);
    }
});

// Check if the file is a txt file
function checkFileType(file, cb) {
    const filetypes = /\.(txt)$/;
    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
    const mimetypes = 'text/plain'

    mimetype = mimetypes === file.mimetype;

    if (mimetype && extname) {
        return cb(null, true);
    } else {
        cb('Error: Only txt files are allowed!');
    }
}

// Set up express
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// Create directories if they don't exist
if (!fs.existsSync('./db')) {
    fs.mkdirSync('./db');
}
if (!fs.existsSync('./uploads')) {
    fs.mkdirSync('./uploads');
}

// Connect to the database
let db = new sqlite3.Database('./db/paragraphs.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
    if (err) {
        console.error(err.message);
    }
    console.log('Connected to the paragraphs database.');
});

// Create the paragraphs table if it doesn't exist
db.run('CREATE TABLE IF NOT EXISTS paragraphs (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT, tag TEXT)', (err) => {
    if (err) {
        console.error(err.message);
    }
    console.log('Created paragraphs table.');
});

// Home page
app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
    /*
    res.write('<h1>Welcome to the Paragraphs App</h1>' +
        '<a href="/file_uploading">Upload a File</a><br>' +
        '<a href="/visualize_paragraphs">Visualize Paragraphs</a><br>' +
        '<a href="/tag_paragraphs">Tag Paragraphs</a>');
    res.end();
     */
});

app.get('/file_uploading', (req, res) => {
    res.sendFile(__dirname + '/file_uploading.html');
});

app.post('/upload_file', upload.single('filetoupload'), async (req, res) => {
    let filename = req.file.filename;

    res.send('File uploaded!<br>' +
        '<a href="/file_uploading">Upload Another File</a><br>' +
        '<a href="/visualize_paragraphs">Visualize Paragraphs</a><br>' +
        '<a href="/tag_paragraphs">Tag Paragraphs</a>');

    fs.readFile('./uploads/' + filename, {encoding: 'utf-8'}, (err, data) => {
        if (err) {
            return console.log(err.message);
        }
        let lines = data.split('\r\n');
        for (let i = 0; i < lines.length; i++) {
            db.run('INSERT INTO paragraphs (text) VALUES (?)', [lines[i]], (err) => {
                if (err) {
                    return console.log(err.message);
                }
            });
        }
    });
});

app.get('/visualize_paragraphs', (req, res) => {
    db.all('SELECT * FROM paragraphs', (err, rows) => {
        if (err) {
            throw err;
        }
        rows.forEach((row) => {
            res.write('<h1>Visualize Paragraphs</h1>');
            res.write(row.text + '<br>');
        });
        res.end();
    });
});

app.get('/tag_paragraphs', (req, res) => {
    let paragraph_id = req.query.paragraph_id;
    let tag = req.query.tag;
    if (paragraph_id && tag) {
        db.run('UPDATE paragraphs SET tag = ? WHERE id = ?', [tag, paragraph_id], function (err) {
            if (err) {
                return console.log(err.message);
            }
            console.log(`Row(s) updated: ${this.changes}`);
        });
        res.send('<h1>Tag Paragraphs</h1>' +
            '<p>Paragraph ' + paragraph_id + ' has been tagged as ' + tag + '</p>');
    } else {
        db.all('SELECT * FROM paragraphs', (err, rows) => {
            if (err) {
                throw err;
            }
            res.write('<h1>Tag Paragraphs</h1>' +
                '<table>');
            rows.forEach((row) => {
                res.write('<tr><td>' + row.id + '</td><td>' + row.text + '</td></tr>');
            });
            res.write('</table>' +
                '<form action="/tag_paragraphs" method="get">' +
                '<label for="paragraph_id">Paragraph ID:</label>' +
                '<input type="text" id="paragraph_id" name="paragraph_id"><br>' +
                '<label for="tag">Tag:</label>' +
                '<input type="text" id="tag" name="tag"><br>' +
                '<input type="submit" value="Submit">' +
                '</form>');
            res.end();
        });
    }
});

app.listen(3000, () => {
    console.log('Example app listening on port 3000!');
});