前端文件上传,循环压缩至指定大小后再提交

项目场景:

项目需求循环文件上传前循环压缩至指定大小后再提交


解决方案:

file.js

export async function fileCompress(file, ms) {
    var maxSize = 1024 * 1024; // 文件最大限制 默认1M
    if (ms) { maxSize = ms * 1024 * 1024 }
    var newFile = await compress(file, maxSize);
    while (newFile.size / 1024 / 1024 >= ms) {
        newFile = await compress(newFile, maxSize);
    }
    return newFile
}
function compress(file, maxSize) {
    return new Promise((resolve, reject) => {
        var newFile = file
        if (file.size > maxSize) { // 如果图片大小大于1m,进行压缩
          // console.log('进行压缩')
            var da = file.size / maxSize
            var w_h = 0.7 //宽高压缩比
            var quality = 0.5
            if (da >= 10) {
                w_h = 0.3
                quality = 0.2
            }
            if (da >= 2 && da < 10) {
                w_h = 0.5
                quality = 0.3
            }
            w_h = 1 //宽高不压缩了
            // 看支持不支持FileReader
            if (!file || !window.FileReader) return;
            // 创建一个 Image 对象
            var image = new Image();
            // 绑定 load 事件处理器,加载完成后执行
            image.onload = function () {
                // 获取 canvas DOM 对象
                var canvas = document.createElement('canvas')
                // 返回一个用于在画布上绘图的环境, '2d' 指定了您想要在画布上绘制的类型
                var ctx = canvas.getContext('2d')
                image.width *= w_h; image.height *= w_h;
                // 获取 canvas的 2d 环境对象,
                ctx.clearRect(0, 0, canvas.width, canvas.height);// canvas清屏
                canvas.width = image.width;// 重置canvas宽高
                canvas.height = image.height;
                ctx.drawImage(image, 0, 0, image.width, image.height);// 将图像绘制到canvas上
                // !!! 注意,image 没有加入到 dom之中
                var newSrc = canvas.toDataURL(file.type, { quality: quality });
                newFile = base64ToFile(newSrc, file.name); // 转成file文件
                // console.log('compress----')
                return  resolve(newFile);
            };
            if (/^image/.test(file.type)) {
                // 创建一个reader
                var reader = new FileReader();
                // 将图片将转成 base64 格式
                reader.readAsDataURL(file);
                // 读取成功后的回调
                reader.onload = function () {
                    // self.imgUrls.push(this.result);
                    // 设置src属性,浏览器会自动加载。
                    // 记住必须先绑定事件,才能设置src属性,否则会出同步问题。
                    image.src = this.result;
                }
            }
        } else {
            return  resolve(newFile);
        }
    })
}
function base64ToFile(dataurl, filename) {
    var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, { type: mime });
}

 如何使用:

<template>
  <div class="picUpload">
    <a-upload
      list-type="picture-card"
      :file-list="fileList"
      :customRequest="customRequest"
      @preview="handlePreview"
      :remove="removePic"
      :multiple="false"
    >
      <div v-if="fileList.length < 1">
        <a-icon type="plus" />
        <div class="ant-upload-text">上传</div>
      </div>
    </a-upload>
    <a-modal 
      wrapClassName="spcModal"
      :closable="false"
      :maskClosable="false"
      v-model="previewVisible"
      width="800px"  
      :footer="null">
      <a-icon @click="handleCancel" class="close" type="close-circle"/>
      <img v-if="type=='image'" alt="example" style="width: 100%" :src="previewFile.realurl" />
      <video v-if="previewVisible&&type=='video'" style="width:100%;display: block;" controls autoplay :src="previewFile.realurl"/>
    </a-modal>
  </div>
</template>

<script>
import { fileCompress } from '@/utils/file.js'
export default {
  name: 'SingleUpload',
  props: {
    value:{
      type:String,
      default:''
    },
    apiUrl: {
      type: String,
      default:'/basedata/v1.0/upload?type=31'
    },
    type:{
      type:String,
      default:'image' //video
    }
  },
  data() {
    return {
      previewVisible: false,
      previewFile: {},
      fileList: []
    }
  },
  mounted(){
    this.valueDeal()
  },
  watch: {
    value: {
      immediate: true,
      handler(newvalue, oldvalue) {
        this.valueDeal()
      }
    }
  },
  methods: {
    valueDeal(){
      var url=this.httpCheck(this.value)
      console.log(url)
      if(url){
        this.fileList = [{
          url: this.type=='image'?url:(url+'?x-oss-process=video/snapshot,t_1000,f_jpg,w_50,h_50,m_fast'),
          realurl:url,
          uid: url,
          name: 'file',
          status: 'done'
        }]
      }else{
        this.fileList=[]
      }
    },
    httpCheck(url){
      if(url){
        if(url.indexOf('http') < 0){
          return 'https://njcyy.oss-cn-beijing.aliyuncs.com/' + url;
        }else{
          return url
        }
      }else{
        return ''
      }
    },
    handleCancel() {
      this.previewVisible = false
    },
    // 查看大图
    handlePreview(file) {
      if (file.status === 'done') {
        this.previewFile = file
        this.previewVisible = true
      }else{
        this.previewFile = {}
      }
    },
    // 删除
    removePic(file) {
      this.fileList = []
      this.$emit('input','')
      return false
    },
    // 自定义上传
    async customRequest(data) {
      var filetype=data.file.type.split('/')[0]
      if(filetype!=this.type){
        this.$message.error('请上传正确的文件类型。')
        return
      }
      const fileId = data.file.uid
      const file = await fileCompress(data.file, 2)
      const fileName = file.name
      const formData = new FormData()
      formData.append('file', file)
      this.api.post(this.apiUrl, formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }).then(res => {
          res=this.httpCheck(res)
          this.fileList=[{
            url: this.type=='image'?res:(res+'?x-oss-process=video/snapshot,t_1000,f_jpg,w_50,h_50,m_fast'),
            realurl:res,
            uid: fileId,
            name: fileName,
            status: 'done'
          }]
          this.$emit('input',res)
        })
    }
  }
}
</script>
<style lang='less' scoped>
  .picUpload {
    height: 110px;
  }
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值