[Record 6] Vue+node+koa2+mysql+nginx+redis, full-stack development of small programs and administrator management system projects-server-side image upload and download

This project needs to involve uploading pictures and displaying pictures on the front end. For this purpose, I will practice picture-related things by myself. It is very interesting, so I will share them.
Implementation idea: The processing method of the server side is to save the file uploaded by the front end locally on the server side, then rename the file name, and then store the path of the image on the server side in the table. When the front end requests the image address, go to the server side to find the file And return to the front-end display.

Create a new common.js file under the routes folder

//common.js
//导入所需模块
const router = require('koa-router')()
const api = require('../controllers/api')
const common = require('../util/comon')
const path = require('path')
const fs = require('fs')
const formidable = require('formidable')
const MimeLookup = require('mime-lookup')
const mime = new MimeLookup(require('mime-db'))
router.prefix('/common')

upload image

//common.js
//上传图片
router.post('/addUploadImg', async (ctx, next) => {
    
    
  console.log(ctx.req)
  let form = new formidable.IncomingForm()
  form.hash = "md5"
  form.multiples = false //默认只能上传一个文件,更多form的配置参考node-formidable
  form.maxFileSize = 2 * 1024 * 1024 //设置文件最大不超过2M
  let type = ['image/png','image/gif','image/jpg','image/jpeg','image/webp']//支持上传的图片类型
  function formImage() {
    
    
    return new Promise((resolve, reject) => {
    
    
      form.parse(ctx.req, async function (err, fields, files) {
    
    //注意:跟express有差异,这里要传入ctx.req
      let file = files['file']
      if (file) {
    
    
        let flag = await common.checkFile(file.type, file.size) //校验文件的大小和类型
        console.log('校验通过'+flag)
        if (flag) {
    
     //文件校验通过
          const oldpath = file['_writeStream'].path //系统缓存上传的文件地址
          const dir = path.join(__dirname, `../common/upload/img`)
          const fileFormat = file.name.split('.')
          file.name = `${
     
     file.hash}_${
     
     Date.now()}.${
     
     fileFormat[fileFormat.length - 1]}` //通过file.hash加时间戳生成文件名
          const newpath = `common/upload/img/${
     
     file.name}`
          if (!fs.existsSync(dir)) {
    
     //先判断文件夹名是否存在,不存在则生成根据XXX生成对应的文件夹
            fs.mkdirSync(dir)
          }
          //如果是非WINDOWS系统,可以用fs.renameSync()来实现,这里为了兼容用了node的pipe来实现
          let readStream = fs.createReadStream(oldpath)
          let writeStream = fs.createWriteStream(newpath)
          readStream.pipe(writeStream) //这里文件已经上传成功
          resolve(ctx.origin + "/" + newpath) //返回完整的文件地址
        } else {
    
    
            reject(null)
          }
      } else {
    
    
          reject(null)
        }
      })
    })
  }
  await formImage()
    .then(res => {
    
     
      ctx.body = {
    
    
        code: 200,
        status: 200,
        data: res,
        message:'上传成功'
      }
    }).catch(err => {
    
     
      ctx.body = {
    
    
        code: 400,
        status: 200,
        data: {
    
    },
        message:'上传失败'
      }
    }
  )
})

Download image

//common.js
//显示图片
router.get('/upload/img/:imgUrl', async (ctx, next) => {
    
    
  url=ctx.url
  let index = url.lastIndexOf('/')
  imgUrl = url.substring(index + 1, url.length)
  let filePath = path.join(__dirname, `../common/upload/img/${
     
     imgUrl}`)
  file = fs.readFileSync(filePath)//读取文件
  // console.log(await watermark.addWatermark(file, options))
  let mimeType = mime.lookup(filePath) //读取图片文件类型
  ctx.set('content-type', mimeType) //设置返回类型
  ctx.body = file //返回图片
})

The download here means that the front end gets the image link and directly img src="https://***/upload/img.123sdjfhg.png" when the server actually needs to respond to this address request from the front end, the above is the receipt After the request, go to the server to get the picture and read it, and then return the file to the front end. Assuming that token verification can be done to request the API, it is recommended to put the route of the "/common/upload/" interface into the whitelist (token-free).

File structure

The final structure presented in the project is: So
Insert picture description here
far, the requirements for uploading and downloading front-end images have been completed, thanks for watching!

Previous: Use swagger to automatically generate interface documents
Previous: Generate request logs

Guess you like

Origin blog.csdn.net/Smell_rookie/article/details/108886254