nodeJS 文件上传

express 下使用body-parser是无法解析multipart/form-data的内容的,如果客户端发来文件内容,使用body-parser中间件是看不到文件的

此时需要引入multer模块,npm install multer -S

var bodyParser = require('body-parser');
var upload = require('multer')({
    dest: 'uploads/' //指定文件上传后存放的位置
})
var app = require('express')();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.listen('8888', function() {
    console.log('.....')
});
app.post('/uploads',upload.any(), function(req, res) {
    console.log(req.fields);
    console.log(req.files); // 此时可以在req.files 已上传内容的信息了
    console.log(req.body);
})

客户端使用FormData上传file Object

<form id="up" name="up" enctype="multipart/form-data" method="POST">
    <input type="file" name="file" id="file"/>
    <input type="submit" id="submit"  />
</form>
<script>
    var form = document.getElementById('up');
    form.addEventListener('submit', function(e) {
        e.preventDefault();
        var data = new FormData(form);
        console.log(data);
        var en = data.entries();
        console.log(en);
        for(var pair of en) {
            console.log(pair);
        }
        xhr.open('post','http://localhost:8888/upload',true);
        xhr.send(data);
    })
</script>

nodeJS文件下载

nodejs 实现下载的方式很多,最简单的一个就是静态化内容。

app.use('/download', express.static(__dirname + '/download'));

也可以采用sendFile的方式发送内容

app.get('/download:filename', (req, res) => {
    var path = __dirname + '/download/' + req.params.filename;
    res.sendFile(path, function (err) {
        if(!err) {
            console.log('发送成功')
        }
    })
})

还可以采用Stream 发送文件

app.get('/download:filename', (req, res, next) {
    let stat = fs.statSync(__dirname +'/uploads/' + req.params.filename);
    res.set({
        'Content-Type': 'application/octet-stream',
        'Content-Disposition': 'attachment',
        'Content-Length': stat.size
    })
    let rd = fs.createReadStream(__dirname +'/uploads/' + result.filename, {
        highWaterMark: 5000000
    }).pipe(res);
    rd.on('end', () => {
        console.log('文件发送完毕');
        try {
            fs.unlink(__dirname +'/uploads/' + result.filename,(err)=>{!err && console.log('文件已被成功下载,已删除文件')});
            result.remove();
        } catch (e) {
            console.log(e);
            res.send(404);
        }
    })
})

最后还有一个简单的方式

app.get('/download:filename', (req, res) => {
    var path = __dirname + '/download/' + req.params.filename;
    res.download(path,(err) => {
        ...
    })
})

关于multer 上传文件后重命名

为了防止文件重复,文件上传后是一个没有后缀名的,并且是一串字符串命名。使用diskStorage可以更改文件名

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/uploads')
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }
})
var upload = multer({ storage: storage })