大文件上传和断点续传(一)

(一)重点核心

(1)FileReader 及 文件流处理方案

(2)基于 Promise 管理文件异步上传

(3)文件上传的两种方案

(4)大文件切片上传

(5)基于 Node 的服务端处理

(二)知识点

文件上传有两种方案:

第一种是基于文件流(form-data),把需要上传的文件放入 form-data 中,最后将 form-data 传入服务器

第二种是基于客户端,客户端需要把文件转化 base64 编码,以 base64 的格式上传服务器 

下面用 element-ui + vue + node + koa 实现一个图片服务器上传的功能

vue + element : 客户端:

客户端的代码还是很简单的

<template>
  <div>
    <el-upload
      class="avatar-uploader"
      action="/upload"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
      :before-upload="beforeAvatarUpload"
    >
      <img v-if="imageUrl" :src="imageUrl" class="avatar">
      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
    </el-upload>
  </div>
</template>

<script>
export default {
    data() {
      return {
        imageUrl: ''
      };
    },
    methods: {
      handleAvatarSuccess(res, file) {
        // res 是接口返回的内容
        // file 是上传的图片信息 
        // { 
        //   "status":"success",
        //   "name":"timg.jpeg",
        //   "size":80828,
        //   "percentage":100,
        //   "uid":1605363808882,
        //   "raw":{"uid":1605363808882},"response":{"code":0,"message":"上传成功!"}
        // }"
        if (res.code === 0) {
          this.imageUrl = URL.createObjectURL(file.raw)
        } else {
          this.$message.error(res.message)
        }
      },
      // 上传之前先校验
      beforeAvatarUpload(file) {
        const isJPG = (/(png|jpeg|jpg|svg|gif)/g).test(file.type)
        const isLt2M = file.size / 1024 / 1024 < 2;

        if (!isJPG) {
          this.$message.error('上传头像图片只能是 JPG 格式!');
        }
        if (!isLt2M) {
          this.$message.error('上传头像图片大小不能超过 2MB!');
        }
        return isJPG && isLt2M;
      }
    }
  }
</script>

<style scoped>
.avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
</style>

node + Koa 服务端:

服务端的代码就比较复杂了。。。

我请求本地node 服务端 upload 接口

默认上传方式:mutipart/form-data,数据格式:form-data,数据包含:file:文件流信息、filename:文件名称 

如果!!服务端想要解析 mutipart 这种格式的数据!必须在服务端使用 mutiparty 这个插件。。。一开始一直用 koa-bodyparser 这个插件,但是始终都获取不到。。。应该是  mutipart 这种格式无法解析,multiparty 这个插件的用法 具体看文档吧~记住服务端文件上传就要用到这个插件

const koa = require('koa')
const fs = require('fs')
const multiparty = require('multiparty')
const path = require('path')
const router = require('koa-router')
const app = new koa()
const Router = new router()
app.use(Router.routes())
Router.post('/upload', (ctx) => {
  var form = new multiparty.Form({
    uploadDir: __dirname + '/upload', // 指定文件存储目录
    maxFilesSize: 2 * 1024 * 1024 //设置单文件大小限制
  })
  form.parse(ctx.req) // 将请求参数传入,multiparty会进行相应处理

  form.on('field', (name, value) => { // 接收到数据参数时,触发field事件
    console.log(name, value)
  })

  form.on('file', (name, file, ...rest) => { // 接收到文件参数时,触发file事件
    // name --->  file
    // file ---> {
    //   fieldName: 'file',
    //   originalFilename: '1.png',
    //   path: '/Users/zhoufangbing/Desktop/node/upload/QIYtZ0bHfdAFTUIA1Na_1P6s.png',
    //   headers: {
    //     'content-disposition': 'form-data; name="file"; filename="1.png"',
    //     'content-type': 'image/png'
    //   },
    //   size: 805971
    // }
    // 可以看出 file.path 这个参数就是图片在服务器上的地址
  })

  form.on('close', () => {  // 表单数据解析完成,触发close事件
    console.log('表单数据解析完成')
  })
  ctx.body = {
    code: 0,
    message: '上传成功!'
  }
})
app.listen(3000, () => {
  console.log('server is running')
})

客户端端口是 8080、服务端端口是3000

客户端直接请求服务端会跨域,所以配置了 whistle 代理

这样客户端上传完毕后:

服务端:

upload 文件夹下也有了这张图片~这就是【文件流】文件上传方式over~

--------------------------------------------------------------------------------------------------

基于客户端base64方式的上传,上一篇文章已经讲过了,使用 FileReader 这个类,道理都一样~

然后base64 的服务端会使用 Buffer,服务端生成图片

但是有一个问题:如果这张图片上传过了 还会继续上传 会重复。。。

这时候就需要一个包 SparkMd5

SparkMd5是做什么的? 

SparkMd5是号称全宇宙最快的前端类包,可以无需上传文件就快速获取本地文件md5.

用这个简单的前端类库就能实现你“秒传”的功能!原理是:每个文件的md5值都是唯一的,这也是很多下载网站,会告诉你原文件的md5是多少,然后下载完毕让你自行去对比下,如果一致,就说明文件是完整的。

正因为每个文件的md5是一样的,那么,我们在做文件上传的时候,就只要在前端先获取要上传的文件md5,并把文件md5传到服务器,对比之前文件的md5,如果存在相同的md5,我们只要把文件的名字传到服务器关联之前的文件即可,并不需要再次去上传相同的文件,再去耗费存储资源、上传的时间、网络带宽。

SparkMd5 是根据文件内容来生成 hash 值的

代码就再下一篇文章中写。。使用 SparkMd5 改造一下就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值