天天看點

[記錄六]Vue+node+koa2+mysql+nginx+redis,全棧開發小程式和管理者管理系統項目——服務端圖檔上傳與下載下傳

本項目需要涉及前端上傳圖檔與顯示圖檔,為此自己實踐一下圖檔相關的東西,挺有意思是以就分享出來。

實作思路:服務端的處理方式是将前端上傳的檔案儲存在服務端本地,然後重命名該檔案名字,再将圖檔在服務端的路徑存入表中,前端請求圖檔位址的時候去服務端找出檔案并傳回給前端顯示。

在routes檔案夾下建立一個common.js檔案

//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')

           

上傳圖檔

//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:'上傳失敗'
      }
    }
  )
})

           

下載下傳圖檔

//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 //傳回圖檔
})

           

這裡下載下傳的意思是前端拿到圖檔連結,直接img src="https:/upload/img.123sdjfhg.png"的時候服務端其實是需要響應前端的這個位址請求的,上面是收到請求後去服務端擷取圖檔并讀取然後傳回檔案回給前端。假設有做token校驗是否可以請求api的話,建議将“/common/upload/”接口的路由放入白名單(免token)中去。

檔案結構

最終在項目中呈現的結構是:

[記錄六]Vue+node+koa2+mysql+nginx+redis,全棧開發小程式和管理者管理系統項目——服務端圖檔上傳與下載下傳

至此就完成前端圖檔上傳和下載下傳的需求了,感謝觀看!

上一篇:使用swagger自動生成接口文檔

上一篇:待寫…

繼續閱讀