使用Multer上传多个文件

19
我正在尝试使用Multer上传多个图片。除了只上传最后选择的一个文件之外,一切都正常运作。
HTML
<form class='new-project' action='/projects' method='POST' enctype="multipart/form-data">
  <label for='file'>Select your image:</label>
  <input type='file' multiple='multiple' accept='image/*' name='uploadedImages' id='file' />
  <span class='hint'>Supported files: jpg, jpeg, png.</span>
  <button type='submit'>upload</button>
</form>

JavaScript

//Define where project photos will be stored
var storage = multer.diskStorage({
  destination: function (request, file, callback) {
    callback(null, './public/uploads');
  },
  filename: function (request, file, callback) {
    console.log(file);
    callback(null, file.originalname)
  }
});

// Function to upload project images
var upload = multer({storage: storage}).any('uploadedImages');

// add new photos to the DB
app.post('/projects', function(req, res){
  upload(req, res, function(err){
    if(err){
      console.log(err);
      return;
    }
    console.log(req.files);
    res.end('Your files uploaded.');
    console.log('Yep yep!');
  });
});

我有一种感觉,似乎错过了什么显而易见的东西...

编辑

我尝试根据Syed的帮助编写的代码:

HTML

<label for='file'>Select your image:</label>
<input type='file' accept='image/*' name='uploadedImages' multiple/>
<span class='hint'>Supported files: jpg, jpeg, png.</span>
<input type="submit" value="uploading_img">

JavaScript

multer = require('multer'),

var upload = multer();

app.post('/projects', upload.array('uploadedImages', 10), function(req, res, err) {
  if (err) {
    console.log('error');
    console.log(err);
  }
  var file = req.files;
  res.end();
  console.log(req.files);
});
3个回答

21

使用Multer上传多个文件

NodeJs代码

设置所需的文件存储

const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 3000

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, path.join(__dirname, './images/'))
    },
    filename: function (req, file, cb) {
            cb(null, file.fieldname + '-' + Date.now() + file.originalname.match(/\..*$/)[0])
    }
});

设置上传文件的大小限制验证规则

const multi_upload = multer({
    storage,
    limits: { fileSize: 1 * 1024 * 1024 }, // 1MB
    fileFilter: (req, file, cb) => {
        if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
            cb(null, true);
        } else {
            cb(null, false);
            const err = new Error('Only .png, .jpg and .jpeg format allowed!')
            err.name = 'ExtensionError'
            return cb(err);
        }
    },
}).array('uploadedImages', 2)

创建主要的路由来上传

app.post('/projects', (req, res) => {
    multi_upload(req, res, function (err) {
        if (err instanceof multer.MulterError) {
            // A Multer error occurred when uploading.
            res.status(500).send({ error: { message: `Multer uploading error: ${err.message}` } }).end();
            return;
        } else if (err) {
            // An unknown error occurred when uploading.
            if (err.name == 'ExtensionError') {
                res.status(413).send({ error: { message: err.message } }).end();
            } else {
                res.status(500).send({ error: { message: `unknown uploading error: ${err.message}` } }).end();
            }
            return;
        }

        // Everything went fine.
        // show file `req.files`
        // show body `req.body`
        res.status(200).end('Your files uploaded.');
    })
});

听取 端口

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
});

HTML代码

<form id="form_el" class='new-project' action='/projects' method='POST' enctype="multipart/form-data">
    <label for='file'>Select your image:</label>
    <input type='file' multiple='multiple' accept='image/*' name='uploadedImages' id='file' />
    <span class='hint'>Supported files: jpg, jpeg, png.</span>
    <button type='submit'>upload</button>
</form>

JAVASCRIPT 代码

form_el.addEventListener('submit', async function (e) {
    const files = e.target.uploadedImages.files;
    if (files.length != 0) {
        for (const single_file of files) {
            data.append('uploadedImages', single_file)
        }
    }
});

const submit_data_fetch = await fetch('/projects', {
    method: 'POST',
    body: data
});

非常感谢。我已经为此奋斗了4个小时。我正在寻找的是单独的附加操作。 - Julian
谢谢,这里是如何使用 multer().array() 方法的链接:https://github.com/expressjs/multer#arrayfieldname-maxcount - arrmani88
在回调函数中,您可以使用Date.now()更改originalfilename并将其保存到磁盘中,但是我该如何在我的路由中进一步获取新名称呢?因为req.files仍然具有您设置的原始文件名而不是新文件名! - Suisse

12

这是一个例子:

var multer  = require('multer');
var upload = multer();

router.post('/projects', upload.array('uploadedImages', 10), function(req, res) {
  var file = req.files;
  res.end();
});
<form action="/projects" method="post" enctype="multipart/form-data">
  <input type="file" name="uploadedImages" value="uploading_img" multiple>
  <input type="submit" value="uploading_img">
</form>

访问Multer获取更多信息。


谢谢Syed,但我刚试了一下,控制台出现了这个错误:error [Function: next] [ { fieldname: 'uploadedImages', originalname: 'Me.jpg', encoding: '7bit', mimetype: 'image/jpeg', buffer: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01 00 01 00 00 ff fe 00 04 2a 00 ff e2 02 1c 49 43 43 5f 50 52 4f 46 49 4c 45 00 01 01 00 00 02 0c 6c 63 ... >, size: 98305 } ] - Runny Yolk
你是只尝试了我的示例还是也应用了你自己的代码? - Noman
我刚刚将我尝试过的代码添加到了我的原始帖子中。与你的差不多,但它没有起作用。 - Runny Yolk

4
我的猜测是,对于每个要上传的文件,你需要重新点击:
<input type='file' multiple='multiple' accept='image/*' name='uploadedImages' id='file' />

如果您这样做,那么只有最后一个选择的文件将被上传,因为您覆盖了之前选择的文件。
要上传多个文件,您必须在文件选择器中一次性选择它们所有。

嘿,你的回答帮了我很多,只是想问一下,如果我想让用户在单击时上传每个文件,那么我该如何防止默认行为呢? - Emma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接