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()
}
})
})
},
标签:el,canvas,http,缩略图,item,let,file,var,上传 来源: https://www.cnblogs.com/Sijin-0109/p/16499011.html