What is the best way to multiple file upload through a single input in nodejs express 4?

前提是你 提交于 2021-02-10 14:21:18

问题


I'm using nodejs with express 4. I'm trying to upload multiple file through a single input field. Also I submit my form through ajax. I'm using express-fileupload middleware for uploading files. When i upload multiple files, it works fine. But when upload a single file, it's not working. html code-

<input type="file" name="attach_file" id="msg_file" multiple />

ajax code-

var data = new FormData();
$.each($('#msg_file')[0].files, function(i, file) {
    data.append('attach_file', file);
});

$.ajax({
    url: '/send_message',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    method: 'POST',
    type: 'POST',
    success: function(data){
      console.log(data);
    }
});

server side js code-

router.post('/send_message', function(req, res, next){
    if (!req.files)
      res.json('No files were uploaded.');

    let sampleFile = req.files.attach_file;
    console.log(sampleFile.length);

    var file_info = [];
    var count = 0;
    sampleFile.forEach(function(ele, key) {
      ele.mv(path.resolve(`./public/upload/${ele.name}`), function(err) {
        if (err){
          console.log(err);
        }else{
          file_info.push(ele.name);
        }
        count++;
        if(sampleFile.length == count){
          res.json({file_name: file_info });
        }
      });
    });
});

if i upload a single file console.log(sampleFile.length); show undefined.


回答1:


After different kind of testing, I found the issue. Everything is ok except when I upload a single file. When ajax send a single file, it was not an array. That's why, length was undefined and forEach did not run. Need to check first, then use mv() function, like as-

if(sampleFile instanceof Array){
    // here is the forEach block
}else{
    // run a single mv() function
}



回答2:


Another complete example and also late answer; in case that help someone.

this is not ajax-based; I used a form in client-side; but you can send data using JS and XHR.

It supports both single and also multiple uploads.

upload.js

'use strict';

const fss = require('fs')
const pth = require('path');
const exp = require('express');
const swg = require('swig');
const efm = require("formidable");
const app = exp();

const thm = swg.compileFile(pth.join(__dirname, '', 'upload.html'));
app.listen(9009);
app.get(`/`, async (q, r) => r.send(thm({ msg: "Select a File to Upload" })));
app.get(`/:msg`, async (q, r) => r.send(thm({ msg: q.params.msg })));
app.post('/upload', (r, q) => {
    const form = efm({ multiples: true });

    form.parse(r, (e, p, files) => {
        let dir = pth.join(__dirname, '', '/media/');
        if (!fss.existsSync(dir)) fss.mkdirSync(dir);

        let uploaded = 0, exists = 0, error = 0;

        //if single file uploaded
        if(!Array.isArray(files.file)){
            files.file=[files.file]
        }

        files.file.forEach(f => {
            let nPth = dir + f.name;
            try {
                fss.accessSync(nPth, fss.F_OK);
                exists++;
            } catch (file_e) {
                let err = fss.renameSync(f.path, nPth);
                if (err) error++; else uploaded++;
            }
        });

        q.redirect(`Upoader -> All: ${files.file.length}, Uploaded: ${uploaded}, Existed: ${exists}, Error: ${error}`);
    });
});

**Its better use "A-Sync" functions.

**I think its also better if you run uploader script on another port.


upload.html

<h3>{{msg}}</h3>
<br/>
<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" multiple>
    <input type="submit">
</form>


来源:https://stackoverflow.com/questions/50560195/what-is-the-best-way-to-multiple-file-upload-through-a-single-input-in-nodejs-ex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!