node文件上传与下载(基于express和multer实现)

811 阅读3分钟

node文件上传与下载

所需要的前置知识:基本的html标签,基本DOM, AJAX, express 等

创建基本的 express 项目

使用express-generator生成基本的项目结构

全局安装express-generator

npm install -g express-generator 

创建express 项目

express upload-download
cd upload-download
npm install

用vs code打开项目

code .

全局安装nodemon, 已方便文件更改时自动更新项目

npm install -g nodemon

安装multer中间件,实现文件的上传功能

npm install --save multer

安装cors中间件,解决跨域问题(我不明白为什么会有跨域问题)

npm install cors

启动项目

先修改项目根目录package.json,将node 改为 nodemon,如图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ztk9Qn4C-1674530175550)(node文件上传与下载.assets/image-20220302112943997.png)]

再启动项目

npm start

客服端

  • public文件下新建index.html

  • 创建html基本结构

  • script标签前创建所需要的标签

<!-- 单文件上传 -->
<input type="file" id="file">
<!-- 多文件上传 -->
<input type="file" id="files" multiple>
<!-- 最简单的下载方式,download属性告诉浏览器要进行文件的下载 -->
<a href="http://127.0.0.1:3000/download" download="">下载</a>
  • 引入 axios
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.min.js"></script>
  • 编写js 代码
const file = document.getElementById('file')
const files = document.getElementById('files')
axios.defaults.baseURL = 'http://127.0.0.1:3000'
// 单文件上传
file.addEventListener('change', async (e) => {
    const formDate = new FormData()
    // 键值对,key,value   键为file, 值为文件
    formDate.append("file", e.target.files[0])
    const {data: res} = await axios.post("/file", formDate, {
        // 因为axios默认的Content-Type 为json,所以需要修改
        headers: {
            "Content-Type": "multipart/form-data"
        }
    })
    console.log(res);
})
// 多文件上传
files.addEventListener('change', async (e) => {
    const formDate = new FormData()
    const files = e.target.files
    // 我不知道为什么不能用forEach
    for(let i = 0; i < files.length; i++){
        formDate.append('files', files[i])
    }
    const {data: res} = await axios.post("/files", formDate, {
        // 因为axios默认的Content-Type 为json,所以需要修改
        headers: {
            "Content-Type": "multipart/form-data"
        }
    })
    console.log(res);
})

服务端

文件上传

单文件上传接口

  • 在app.js中配置 cors中间件,解决跨域问题
const cors = require('cors')
app.use(cors())
var express = require('express')
var router = express.Router()
const multer = require('multer')
// multer配置
const upload = multer({ dest: 'assets/uploads' })
// 单文件上传接口
    router.post('/file', upload.single('file'), (req, res) => {
      console.log(req.file)
      res.send('ok')
    })

module.exports = router

服务器端控制台打印信息

{
  fieldname: 'file',
  originalname: 'yunyoujun.png',
  encoding: '7bit',
  mimetype: 'image/png',
  destination: 'assets/uploads',
  filename: 'fc6acbf4b3348b82d85b6cf3edc967dd',
  path: 'assets\\uploads\\fc6acbf4b3348b82d85b6cf3edc967dd',
  size: 773524
}

客服端控制台打印信息

ok

assets/uploads目录下生成了文件名为fc6acbf4b3348b82d85b6cf3edc967dd的文件,vs code显示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XUWdhHC3-1674530175551)(node文件上传与下载.assets/image-20220302121147054.png)]

fc6acbf4b3348b82d85b6cf3edc967dd加上文件名后缀.png就可以正常访问文件了


配置multer实现自动修改文件名

const storage = multer.diskStorage({
  // 上传文件的目录
  destination: function (req, file, cb) {
    cb(null, 'assets/uploads')
  },
  // 上传文件的名称
  filename: function (req, file, cb) {
    cb(null, file.originalname)
  }
})
// multer 配置
const upload = multer({
  storage
})

多文件上传

// 多文件上传
// upload.array('formDate中的字段名', 最大上传数量)
router.post('/files', upload.array('files', 4), (req, res) => {
  console.log(req.files)
  res.send('ok')
})

文件下载

node 文件下载设置响应头······的content-type 与 Content-Disposition来告诉浏览器,响应结果属于文件下载,准备好接收文件

在app.js中共享/assets/downloads/文件夹

app.use(express.static(path.join(__dirname, './assets/downloads/')))

下载接口

先引入path模块

const path = require('path')

编写接口

router.get('/download', (req, res) => {
  const filePath = path.join(__dirname, '../assets/downloads/yunyoujun.png')
  res.download(filePath)
})

将文件上传到mysql 中

文件上传

安装mysql 模块

npm i mysql
  • 在项目根目录创建db文件夹
  • db文件夹中创建index.js
  • 配置连接池
const mysql = require('mysql')
const db = mysql.createPool({
  host: '192.168.188.100',
  user: 'db-test',
  password: 'admin123',
  database: 'db-test'
})

module.exports = db

routes/index.js中导入db对象


修改储存模式

multer.diskStorage 修改为 multer.memoryStorage

// 将文件储存在 Buffer 中
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })

此时的req.file对象

{
  fieldname: 'file',
  originalname: '-6e4e28c3bf13a6ab.gif',
  encoding: '7bit',
  mimetype: 'image/gif',
  buffer: <Buffer 47 49 46 38 39 61 f0 00 f0 00 f7 ff 00 a6 7b 6e 8b 6a 53 29 21 18 ce 39 29 24 16 12 93 71 68 ff e7 ce fe 72 5a ff b5 5a 18 56 2d 9d 53 37 ff
ff ff d0 ... 1520754 more bytes>,
  size: 1520804
}

上传到mysql 中

const file = req.file
const data = {
    value: file.buffer
  }
const sql = 'INSERT INTO file SET ?'
db.query(sql, data, (err, results) => {
    if (err) {
        return console.log(err.message)
    }
})

sql 语句还可以为INSERT INTO file (value) VALUES (?)

文件下载

router.get('/dw', (req, res) => {
  const sql = 'SELECT * FROM file'
  db.query(sql, (err, results) => {
    if (err) {
      return res.send(err.message)
    }
    res.set({
      'Content-Type': 'image/jpeg',
      'Accept-Ranges': 'bytes',
      'Content-Disposition': 'attachment; filename="filename.jpg"'
    })
    res.send(results[0].value)
  })
})