乐趣区

关于前端:免费开源基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之文件上传十

基于 Vue 和 Quasar 的前端 SPA 我的项目实战之文件上传(十)

回顾

通过之前一篇文章 基于 Vue 和 Quasar 的前端 SPA 我的项目实战之数据导入(九)的介绍,实现了业务数据批量导入性能,本文次要介绍文件上传相干内容。

简介

crudapi 反对附件字段,表字段外面保留的是文件 url 字符串。附件能够通过其它文件管理系统比方阿里云的 OSS 进行上传,或者应用零碎自带的文件治理 API 进行上传,包含一般文件上传和大文件切片上传两种形式。

UI 界面


文件上传


大文件上传

API

文件上传 API,包含一般文件上传和大文件切片两个性能,具体的通过 swagger 文档能够查看。通过 axios 封装 api,名称为 file

import {axiosInstance} from "boot/axios";

const HEADERS = {"Content-Type": "multipart/form-data"};

const file = {upload: async function(data, progressCallback) {console.log("file->upload")
    return axiosInstance.post(`/api/file` , data,
      {
        headers: HEADERS,
        onUploadProgress:  (progressEvent) => {if (progressCallback) {progressCallback(progressEvent)
          }
        }
    });
  },
  bigUpload: async function(data, progressCallback) {console.log("file->bigUpload")
    return axiosInstance.post(`/api/file/big` , data,
      {
        headers: HEADERS,
        onUploadProgress:  (progressEvent) => {if (progressCallback) {progressCallback(progressEvent)
          }
        }
    });
  }
};

export {file};

外围代码

CFile 组件

 <q-toggle v-model="enableBigFile" label="开启大文件上传模式" />

  <div v-show="!enableBigFile" class="q-py-md">
    <q-file v-model="normalFile" label="请抉择文件(一般上传)">
      <template v-slot:prepend>
        <q-icon name="attach_file" />
      </template>
      <template v-slot:after>
        <q-btn round dense flat icon="send" @click="onSubmitClick" />
      </template>
    </q-file>
  </div>

  <div v-show="enableBigFile" class="q-py-md">
    <q-file v-model="bigFile" @input="bigFileAdded" label="请抉择文件(大文件上传)">
      <template v-slot:prepend>
        <q-icon name="attach_file" />
      </template>
      <template v-slot:after>
        <q-btn round dense flat icon="flight_land" @click="onBigSubmitClick" />
      </template>
    </q-file>
  </div>

通过 toggle 切换上传模式,如果是小文件采纳一般的形式即可。

一般上传

async onSubmitClick() {console.info("CFile->onSubmitClick");

  if (!this.normalFile) {
    this.$q.notify({
      message: '请抉择文件!',
      type: 'warning'
    });
    return;
  }

  this.$q.loading.show({message: "上传中"});

  try {let form = new FormData()
    form.append('file', this.normalFile);

    this.fileInfo = await fileService.upload(form, (e)=> {console.info(e);
    });
    this.$q.loading.hide();
    this.$emit("input", this.fileInfo);
  } catch (error) {this.$q.loading.hide();
    console.error(error);
  }
}

大文件切片上传

bigFileAdded(f) {console.info("CFile->fileAdded");

  if (!f) {console.info("CFile->cancel");
    return;
  }

  this.$q.loading.show({message: "文件筹备中"});

  FileMd5(f, this.chunkSize, (e, md5) => {
    this.md5 = md5;
    console.info(e);
    console.info(md5);
    this.$q.loading.hide();});
},

async onBigSubmitClick() {console.info("CFile->onBigSubmitClick");

  if (!this.bigFile) {
    this.$q.notify({
      message: '请抉择文件!',
      type: 'warning'
    });
    return;
  }


  this.$q.loading.show({message: "上传中"});

  try {let chunks = this.getChunks();

    let reqs = [];
    for (let i = 0; i < chunks; ++i) {reqs.push(this.uploadWithBlock(i));
    }

    await Promise.all(reqs)
    .then((datas) => {console.info(datas);
      this.checkFinished(datas);
    });
  } catch (error) {this.$q.loading.hide();
    console.error(error);
  }
}

大文件如果采纳一般的上传形式,可能因为网络的起因速度比较慢,而且不稳固,所以采纳切片的形式进行多线程上传。具体原理如下:首先计算文件 MD5,后盾会依据 MD5 惟一确定是同一个文件,同一个文件的不同 block 依据大小和偏移量会写在雷同文件对应的地位,当最初一个 block 上传胜利后,示意上传完结。分片大小默认为 20MB,能够配置为须要的值,前端通过 Promise.all 的 ajax 调用形式能够实现多线程同时上传。

文件表为例


文件表的“链接”字段设置类型为“附件 ATTACHMENT”,增加业务数据页面会主动采纳 CFile 组件。


抉择大文件之后,点击上传图标,通过 chrome 网络申请发现,多线程分片上传模式曾经启动,上传完结之后能够查看下载。

小结

本文次要介绍了文件上传性能,包含一般上传模式和大文件切片上传模式,大文件切片上传模式通过优化后很容易反对断点续传和秒传,后续会依据需要优化文件上传性能。

demo 演示

官网地址:https://crudapi.cn
测试地址:https://demo.crudapi.cn/crudapi/login

附源码地址

GitHub 地址

https://github.com/crudapi/crudapi-admin-web

Gitee 地址

https://gitee.com/crudapi/crudapi-admin-web

因为网络起因,GitHub 可能速度慢,改成拜访 Gitee 即可,代码同步更新。

退出移动版