vue+element+koa 上传/下载文件

2,408 阅读1分钟

vue+element+koa 上传/下载文件

file.js

const Koa = require('koa')
const app = new Koa()
const koaBody = require('koa-body') // 将请求报文和响应报文转化成可读数据
const Router = require('koa-router') // 路由中间件
const send = require('koa-send') // 将静态文件转换成文件流,提供下载功能
const cors = require('koa2-cors') // 跨域
const fs = require('fs') // 文件系统中间价

const router = new Router()

router.get('/', async ctx => {
  ctx.body = '欢迎'
})

// 下载
router.get('/download', async ctx => {
  const path = '/static/抖音运营sop整理.pdf'
  ctx.attachment(path)
  await send(ctx, path)
})

// 上传
router.post('/upload', async ctx => {
  // 文件流在ctx.request.files.file中,附带参数在ctx.request.body中
  console.log(ctx.request.files.file, ctx.request.body)
  const file = ctx.request.files.file
  const reader = fs.createReadStream(file.path)
  const upStream = fs.createWriteStream(`./static/${file.name}`)
  reader.pipe(upStream)
  return ctx.body = { 'msg': '上传成功', 'type': ctx.request.body.type }
})

app
.use(koaBody({
  multipart: true, // 允许上传或下载文件
  formidable: {
    maxFileSize: 200*1024*1024 // 限制上传或下载的文件的大小
  }
}))
.use(cors({
  origin: function(ctx) {
    // 可以放行/限制某些域名请求的跨域
    if (ctx.url === '/test') {
      return false;
    }
    return '*';
  },
  exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
  maxAge: 5,
  credentials: true,
  allowMethods: ['GET', 'POST', 'DELETE'],
  allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}))
.use(router.routes())
.use(router.allowedMethods())

app.listen(3001, () => {
  console.log('koa is listening in 3001')
})

file.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"/>
  <title>文件系统</title>
</head>
<body>
  <div id="app">
    <el-button @click="download">下载文件</el-button>
    <el-upload
      class="upload-demo"
      action="http://localhost:3001/upload"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :before-upload="beforeUpload"
      :on-success="handleSuccess"
      :http-request="upload"
      :data="additionalData"
      multiple
      :limit="3"
      :on-exceed="handleExceed"
      :file-list="fileList">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
  </div>
</body>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
  new Vue({
    el: '#app',
    data() {
      return {
        fileList: [],
        additionalData: { type: 'init' }
      }
    },
    methods: {
      download() {
        window.open('http://localhost:3001/download', 'self')
      },
      upload(e) {
        console.log(e)
        let formData = new FormData()
        formData.append('file', e.file)
        formData.append('type', 'test')
        axios({
          method: 'post',
          url: 'http://localhost:3001/upload',
          headers: {
            'Content-Type': 'multipart/form-data'
          },
          data: formData
        }).then(res => {
          console.log('res', res)
        })
      },
      beforeUpload(file) {
        this.additionalData = { 'type': 'test' }
        return new Promise(resovle => {
          this.$nextTick(() => {
            resovle(true)
          })
        })
      },
      handleRemove(file, fileList) {
        console.log(file, fileList);
      },
      handlePreview(file) {
        console.log(file);
      },
      handleExceed(files, fileList) {
        this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
      },
      beforeRemove(file, fileList) {
        return this.$confirm(`确定移除 ${ file.name }?`);
      },
      handleSuccess(res, file, fileList) {
        console.log('上传成功:', res)
      }
    }
  })
</script>
</html>