1

我有一个使用 Multer 用 NodeJS 编写的简单上传应用程序,效果很好。这是代码:

var express = require('express'),
    bodyParser = require('body-parser'),
    qs = require('querystring'),
    multer = require('multer'),
    logger = require('morgan');

var config = require('./config'),
    oauth = require('./oauth');

function extractExtension(filename) {
    return filename.split('.').pop();
}

function getRandom(min, max) {
    return Math.floor(Math.random() * max) + min;
}


var app = express();
//app.use(cors());

// Add headers
app.use(function(req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Authorization,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

// Multer
var momentUpload = multer({
    dest: './uploads/',
    limits: {
        fileSize: 256 * 1024 * 1024
    },
    rename: function(fieldname, filename) {
        return Date.now() + '-' + getRandom(100000, 999999) + '.' + extractExtension(filename);
    },
    onFileUploadStart: function(file) {
        console.log(file.originalname + ' is starting ...')
    },
    onFileUploadComplete: function(file) {
        console.log(file.fieldname + ' uploaded to  ' + file.path)
    }
}).single('file');

app.set('port', 4000);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

app.post('/file/upload', [oauth.ensureAuthenticated, momentUpload, function(req, res) {
    console.log(req.body); // form fields
    console.log(req.file); // form files

    res.status(204).end();
}]);

// Start the Server
app.listen(app.get('port'), function() {
    console.log('Metadata store env: ' + config.METADATASTORE_ENV);

    console.log('Express server listening on port ' + app.get('port'));

    firebase.authenticate();
    console.log('Connected to Firebase');
});

然而,问题是 Multer 的配置似乎根本不起作用。destPath 有效,文件出现在我提供的文件夹 (./uploads/) 中。允许更大的文件大小(例如 400MB 的文件,而选项明确指出 256MB),并且回调函数不会被触发一次。没有错误信息。知道我在这里做错了什么吗?我按照 Google 和官方页面上的指南进行操作,但无法正常工作。

4

1 回答 1

2

首先,multer最近改变了它的API,所以它不再接受renameonFileUploadStart或者onFileUploadComplete

我们可以在这里查看 API https://github.com/expressjs/multer,让我们来分析一下新的工作方式!

注意:如果您还没有更新您的 multer 版本,我强烈建议您更新,因为旧版本被怀疑存在安全漏洞。

基本用法

Multer 接受一个选项对象,其中最基本的是 dest 属性,它告诉 Multer 将文件上传到哪里。如果您省略选项对象,文件将保存在内存中并且永远不会写入磁盘。

默认情况下,Multer 会重命名文件以避免命名冲突。重命名功能可根据您的需要进行定制。options 对象还接受fileFilter(控制上传哪些文件的函数)和limits(指定大小限制的对象)参数。

因此,您的代码将如下所示(仅涉及 multer 部分并考虑到您希望使用所有不必要的选项):

// Multer
var momentUpload = multer({
    dest: './uploads/',
    limits: {
        fileSize: 256 * 1024 * 1024
    },
    fileFilter: function(req, file, cb) {

        // The function should call `cb` with a boolean
        // to indicate if the file should be accepted

        // To reject this file pass `false`, like so:
        cb(null, false)

        // To accept the file pass `true`, like so:
        cb(null, true)

        // You can always pass an error if something goes wrong:
        cb(new Error('I don\'t have a clue!'))

    }
}).single('file');

如果您想更好地控制文件的存储,可以使用存储引擎。您可以创建自己的或简单地使用可用的。

可用的有:diskStorage将文件存储在磁盘上或memoryStorage将文件作为Buffer对象存储在内存中。

既然您显然想将文件存储在磁盘中,那么让我们来谈谈diskStorage.

有两个选项可用:destinationfilename

destination用于确定上传的文件应存储在哪个文件夹中。这也可以作为字符串给出(例如'/tmp/uploads')。如果没有给出目的地,则使用操作系统的临时文件默认目录。

注意:在将目标提供为函数时,您有责任创建目录。传递字符串时,multer 将确保为您创建目录。

filename用于确定文件夹内的文件应命名为什么。如果没有给出文件名,每个文件将被赋予一个不包含任何文件扩展名的随机名称。

因此,您的代码(仅涉及 multer 部分)将如下所示:

// Multer
//Storage configuration
var storageOpts = multer.diskStorage({
    destination: function (req, file, cb) {
        //Choose a destination
        var dest = './uploads/';

        //If you want to ensure that the directory exists and 
        //if it doesn't, it is created you can use the fs module
        //If you use the following line don't forget to require the fs module!!!
        fs.ensureDirSync(dest);
        cb(null, dest);
    },
    filename: function (req, file, cb) {

        //here you can use what you want to specify the file name
        //(fieldname, originalname, encoding, mimetype, size, destination, filename, etc)
        cb(null, file.originalname);
    }
});

var momentUpload = multer({
    storage: storageOpts,
    limits: {
        fileSize: 256 * 1024 * 1024
    },
    fileFilter: function(req, file, cb) {

        // The function should call `cb` with a boolean
        // to indicate if the file should be accepted

        // To reject this file pass `false`, like so:
        cb(null, false)

        // To accept the file pass `true`, like so:
        cb(null, true)

        // You can always pass an error if something goes wrong:
        cb(new Error('I don\'t have a clue!'))

   }
}).single('file');

希望它有所帮助!:)

于 2015-10-13T09:54:05.313 回答