el-upload使用http-request切片上传以及使用base64压缩图片展示缩略图

html部分

<el-upload
class="avatar-uploader"
action="/file/upload_file/"
:on-remove="() => handleRemove(item)"
:http-request="(params) => httpUploadFile(params,item)"
:before-upload="beforeUpload"
accept="image/jpeg"
:file-list="item.fileList">
	<img v-if="item.value[0].thumb_url" :src="item.value[0].thumb_url" alt="" class="avatar" style="max-width: 500px;">
	<i v-else class="el-icon-plus avatar-uploader-icon"></i>
	<div slot="tip" class="el-upload__tip" v-if="item.value[0].url && item.value[0].thumb_url">
		<a :href="item.value[0].url" :download="item.value[0].name"><el-button type="success" size="small">下载原图</el-button></a>
		<el-button size="small" type="danger" @click="handleRemove(item)">删除图片</el-button>
	</div>
</el-upload>
<el-progress v-if="item.value[0].percent && item.value[0].percent != 0 && !(item.value[0].url && item.value[0].thumb_url)" :percentage="item.value[0].percent"></el-progress>

因为外部有循环所以里面的绑定值都有item,自行替换即可。

Javascript部分

// 取代原有的上传
httpUploadFile(params,item){
    item.value[0].name = params.file.name
    this.cutFile(params,item)
},

先替换原有的上传事件

// 大文件切片,async跟await可以传完一个再传下一个,需要同时传就去掉
async cutFile(params,item){
    let file = params.file
    let length = 1024 * 1024 * 5; // 这里是每一个分片的大小
    let total_number = Math.ceil(file.size / length); // 使用进一法,来确定分片的个数
    let start = 0; // 分片的初始位置
    let end = length; // 分片的结束位置
    let parr = []; // 这里为promise.all方法准备一个数组
    let percentInfo = {
        fileSize:file.size,
        length:length,
    } //给进度条用的
    for (let i = 1; i <= total_number; i++) {
        // 这里开始分片,并且把每一个分片上传到服务器
        let blob = file.slice(start, end); // 得到一个分片
        start = end; // 调整下一个分片的起始位置
        end = start + length; // 调整下一个分片的结束位置
        if (end > file.size) {
            end = file.size; // 这里对最后的一个分片结束位置进行调整
        }
        let formdata = new FormData(); // 创建一个FormData对象,准备传送数据
        formdata.append("file", blob); // 将分片数据放入formdata
        formdata.append("blob_num", i); // 这是第几块
        formdata.append("total_blob_num", total_number); // 总的几块
        formdata.append("file_name", file.name); // 文件名
        // formdata组装好之后,调用pro()函数,返回一个promise对象,并把它放入parr数组中,方便后面的promise.all方法使用
        parr.push(await _this.submitCutFile(formdata,item,percentInfo));
    }
// 以上for循环结束之后,parr数组中就全部是分片上传的promise的对象了,此时我们使用promise.all方法,等待所有上传都成功执行后,再向服务器发送一个请求,也就是上传完成,让服务器组装分片的请求
    Promise.all(parr).then(res=>{
        if(res.length == parr.length){ // 如果返回成功的数组长度和parr的数组长度相等,说明分片全部上传成功
            this.fileTobase64(file).then(res =>{
                _this.compressImg(res,1000,0.5).then(res2 =>{
                    resolve = item.value[0].thumb_url = res2
                })
            })
            item.value[0].url = JSON.parse(res[res.length-1]).file_path
        }
    }).catch(res =>{
        _this.$message.warning("上传失败,请重新上传")
    })
},

把文件切片,使用了async跟await是为了传完一个切片完再传下一个,不需要的话去掉就行
在promise.all的是为了把大图片变成base64并用canvas压缩变成缩略图方便预览

// 将上传的文件先转为base64进行预览
 fileTobase64(file){
     return new Promise((resolve, reject) => {
         var reader = new FileReader();
         reader.onload = function(e){
             resolve(e.target.result)
         }
         reader.readAsDataURL(file)
     })
 },
 // 把base64图片渲染成canvas进行压缩
 compressImg(base64String, w, quality) {
     var getMimeType = function(urlData) {
         var arr = urlData.split(",");
         var mime = arr[0].match(/:(.*?);/)[1];
         return mime;
     };
     var newImage = new Image();
     var imgWidth, imgHeight;

     var promise = new Promise(resolve => (newImage.onload = resolve));
     newImage.src = base64String;
     return promise.then(() => {
         imgWidth = newImage.width;
         imgHeight = newImage.height;
         var canvas = document.createElement("canvas");
         var ctx = canvas.getContext("2d");
         if (Math.max(imgWidth, imgHeight) > w) {
             if (imgWidth > imgHeight) {
                 canvas.width = w;
                 canvas.height = (w * imgHeight) / imgWidth;
             } else {
                 canvas.height = w;
                 canvas.width = (w * imgWidth) / imgHeight;
             }
         } else {
             canvas.width = imgWidth;
             canvas.height = imgHeight;
         }
         ctx.clearRect(0, 0, canvas.width, canvas.height);
         ctx.drawImage(newImage, 0, 0, canvas.width, canvas.height);
         var base64 = canvas.toDataURL(
             getMimeType(base64String),
             quality
         );
         return base64;
     });
 },

上传每个切片,并正确设置进度条

 // 上传切片,设置进度条
 submitCutFile(formData,item,percentInfo){
     let i = formData.get('blob_num')
     console.log(i)
     console.log(formData.get('total_blob_num'))
     return new Promise((resolve,reject)=>{
         $.ajax({
             type:"post",
             url:"/cl/test/test_upload/", // 后台上传文件的地址
             data:formData,
             contentType: false, // 这个不能少,ajax上传文件是不能少的
             processData: false, // 这个不能少,ajax上传文件必传false
             xhr: function() {
                 let newxhr = new XMLHttpRequest()
                 // 添加文件上传的监听
                 // onprogress:进度监听事件,只要上传文件的进度发生了变化,就会自动的触发这个事件
                 newxhr.upload.onprogress = function(e) {
                     console.log(e)
                     let percent = (((i-1)*percentInfo.length + e.loaded)/percentInfo.fileSize)*100
                     item.value[0].percent = Number(percent.toFixed(1))
                 }
                 return newxhr
             },
             success:function(res){
                 resolve(res)
             },
             fail: function () {
                 reject()
             }
         })
     })
 },
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值