头像上传

@multer
Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件
请仅在有需要处理上传文件的路由中使用,以防恶意操作 - Only use this function on routes where you are handling the uploaded files
更多信息,请访问 NPM - multer
上传类型
single(fieldname)

Accept a single file with the name fieldname. The single file will be stored in req.file.

array(fieldname[, maxCount])

Accept an array of files, stored in req.files

fields(fields)

Accept a mix of files, stored in req.files

[
  { name: 'avatar', maxCount: 1 },
  { name: 'gallery', maxCount: 8 }
]
none()

Accept only text fields

any()

Accepts all files

基本步骤
可以在之前的资源服务器上进行
创建服务器目录
初始化
安装multer依赖
在服务器创建上传目录
创建服务器脚本
引入依赖
配置上传存储:推荐使用storage而不是dest;如果仅仅处理文本数据,可以不指定存储
创建上传实例
响应路由
开启服务
后续接口中,利用名字区分不同的用途,如使用image代表普通图片;使用avatar代表头像。具体应根据开发要求制定接口
single()
上传单张图片;可以同时提交数据
上传单张图片
上传单张图片接口
分类 说明
API接口 /upload
name属性 image
完整流程
静态资源服务器的基础继续开发
安装依赖
npm install multer --save
引入 multer、path;path 用以解析获取文件扩展名
const multer = require('multer')
const path = require('path')
在静态资源目录 public 中,创建上传目录 upload;上传目录要 提前 创建好;如果不指定,上传的内容将保留在内存中
配置存储 storage:指定上传目录,如 upload

Multer accepts an options object, the most basic of which is the dest property, which tells Multer where to upload the files. In case you omit the options object, the files will be kept in memory and never written to disk.

In an average web app, only dest might be required.

more control over your uploads, use the storage option instead of dest.

使用 diskStorage 配置可以更好控制上传细节,如改名;有了diskStorage,可以放弃 dest 配置

使用时间戳为上传图片拼接名字

文件的存储位置和命名方式,根据实际情况定制,如可以按照学号+姓名命名头像文件

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, __dirname + '/public/upload')
  },
  filename: (req, file, cb) => {
    let ext = path.extname(file.originalname)
    cb(null, file.fieldname + Date.now() + ext)
  }
})
创建 multer示例 - 可以看出,只需要指定一个存储即可
const upload = multer({
  storage: storage
})        
响应路由 - 以上传单文件single(name)为例;name是网络请求中为图片指定的name属性,即:只接收请求中name属性指定的图片文件;可以根据不同的name上传不同用途的图片,如name为img代表普通图片,为avatar代表头像图片等等

req.file可以获取到具体的文件信息

app.post('/upload', upload.single('image'), (req, res) => {
  res.send({
    err: 0,
    url: 'http://127.0.0.1:3000/upload/' + req.file.filename
  })
})

默认情况下,只是简单的将文件上传到指定目录;不会解析文件信息,如文件名或文件后缀

{
  fieldname: 'image',
  originalname: 'XG7mQxuM7nYJ787bce43d31211e2a9fb482c28888418.png',
  encoding: '7bit',
  mimetype: 'image/png',
  destination: 'upload',
  filename: '7d9d07bdadd775e054e0e0e00fe2d444',
  path: 'upload\\7d9d07bdadd775e054e0e0e00fe2d444',
  size: 91117
}
完整服务端代码index.js如下
const express = require('express')
const multer = require('multer')
const path = require('path')

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'public/upload')
  },
  filename: (req, file, cb) => {
    let ext = path.extname(file.originalname)
    cb(null, file.fieldname + Date.now() + ext)
  }
})

const upload = multer({
  storage: storage
})

const port = 3000
const app = express()
app.use(express.static('./public'));

app.post('/upload', upload.single('image'), (req, res) => {
  console.log(req.file)
  //res.send(req.file)
  res.send({
    err: 0,
    url: 'http://127.0.0.1:3000/upload/' + req.file.filename
  })
})

app.listen(port, () => {
  console.log('server now is at 127.0.0.1:3000');
})
上传单张图片和数据
按照学号和姓名命名图片
分类 说明
API接口 /upload/avatar
图片 avatar
学号 usn
姓名 uname
原生HTML开发,需要显式的指定表单 enctype 为 multipart/form-data
client - HTML
<form action="http://127.0.0.1:3000/upload/avatar" enctype="multipart/form-data" method="post">
  <input type="file" name="avatar">
  <input type="text" placeholder="your sn" name="usn">
  <input type="text" placeholder="your name" name="uname">
  <button>submit</button>
</form>
server
router.post('/mix', upload.single('uimg'), (req, res) => {
  res.send({ msg: 'ok' })
})
封装multer为upload.js
提示:把upload暴露出去
说明:引入时间格式依赖;增加了创建目录功能
const multer = require('multer')
const fs = require('fs');
const path = require('path')
const sd = require('silly-datetime');

// Set up storage for uploaded files
const storage = multer.diskStorage({
  destination: (req, file, callback) => {
    let date = sd.format(new Date(), 'YYYYMMDD');
    let dir = path.join('public/upload', date)
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir)
    }
    callback(null, dir);
  },
  filename: (req, file, callback) => {
    let ext = path.extname(file.originalname)
    callback(null, file.fieldname + Date.now() + ext);
  }
});

// Create the multer instance
const upload = multer({
  storage: storage
});

module.exports = upload
none()
应用三、提交表单数据 none()
说明:无须配置存储,仅需创建multer实例
不借助multer也可以使用原生formData提交,详情请参考formDataform
API接口和name属性
分类 说明
API接口 /upload/text
名字 uname
密码 upass
client - HTML
<form action="http://127.0.0.1:3000/upload/text" enctype="multipart/form-data" method="post">
  <input type="text" placeholder="your name" name="uname">
  <input type="password" placeholder="your pass" name="upass">
  <button>submit</button>
</form>
server
router.post('/text', upload.none(), (req, res) => {
  res.send({ msg: 'ok' })
})
array()
应用四、上传多个图片 array()
利用<input>的multiple属性选择多个图片
<input type="file" name="img" multiple>
router.post('/array', upload.array('img', 9), (req, res) => {
  res.send({
    err: 0,
    msg: 'ok',
    data: req.body,
    file: req.files
  })
})
fields()
应用五、上传多个图片 fields()