vue 移动端input上传图片之处理图片
Sonder
2023-02-16
6257字
16分钟
浏览 (1.9k)
前端开发中会有各种上传文件的需求,今天我们来说说上传图片
上传图片
<input type="file" @change="imageChange($event)" accept="image/*" multiple />
type:”file” 上传文件的格式
multiple :multiple 多张上传(不设置的话就是单张上传啦)
accept:image/* 上传类型(这里设置的是image/*,就是上传图片的所有类型啦,我们可以更加项目需求设置不同的类型 image/gif, image/jpeg)
点击input 选择图片触发@change="imageChange($event)"
事件
选择后我们的到的是二进制流,
现在各大手机拍出的照片大小不一样,我们需要压缩图片,还要处理一部分手机照片上传后会有旋转的问题
// 上传图片
imageChange(e){
//e 选择图片后返回的所有参数 是数组的形式
var imgs = e.target.files || e.dataTransfer.files;
if (!imgs.length) return;
let self = this
for(var i=0;i<imgs.length;i++) {
this.blobToBase64(imgs[i]) //转成 base64
}
},
获取到的二进制文件 转 base64文件
这里需要引入插件 import EXIF from “exif-js”; ios上传照片会有旋转的问题
npm install exif-js -s
/**
* 获取到的二进制文件 转 base64文件
* @param blob
*/
blobToBase64 (blob) {
const self = this // 绑定this
const reader = new FileReader() //实例化一个reader文件
reader.readAsDataURL(blob) // 添加二进制文件
reader.onload = function (event) {
const base64 = event.target.result // 获取到它的base64文件
const scale = 0.3 // 设置缩放比例 (0-1)
if(self.isiOS){ //判断是否是ios
//ios上传图片时会根据拍照时是横屏还是竖屏拍摄,图片会旋转的,我们要将图片旋转成正常
EXIF.getData(blob, function() {
EXIF.getAllTags(this);
var orientation = EXIF.getTag(this, 'Orientation');
self.compressImg(base64,orientation, scale, self.gotoService) // 调用压缩方法
//self.gotoService 压缩后上传至服务器
});
}else{
self.compressImg(base64,0, scale, self.gotoService) // 调用压缩方法
}
}
},
压缩图片方法
/* 压缩图片方法
* @param base64 ----baser64文件
* @param scale ----压缩比例 画面质量0-9,数字越小文件越小画质越差
* @param callback ---回调函数
*/
compressImg (base64, orientation,scale, callback) {
// 处理缩放,转换格式
let self = this;
const img = new Image() //new 一个图片
img.src = base64
img.onload = function () {
const canvas = document.createElement('canvas') // 用canvas来压缩
const ctx = canvas.getContext('2d')
canvas.setAttribute('width', this.width)
canvas.setAttribute('height', this.height)
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
if(isIos){ //ios处理图片旋转
if(orientation != "" && orientation != 1){
switch(orientation){
case 6://需要顺时针(向左)90度旋转
self.rotateImg(img,'left',canvas);
break;
case 8://需要逆时针(向右)90度旋转
self.rotateImg(img,'right',canvas);
break;
case 3://需要180度旋转
self.rotateImg(img,'right',canvas);//转两次
self.rotateImg(img,'right',canvas);
break;
}
}
}
// 转成base64 文件
let base64 = canvas.toDataURL('image/jpeg')
// 根据自己需求填写大小 我的目标是小于2兆
while (base64.length > 1024 * 1024 * 2) {
scale -= 0.01
base64 = canvas.toDataURL('image/jpeg', scale)
}
// baser64 TO blob 这一块如果不懂可以自行百度,我就不加注释了
const arr = base64.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bytes = atob(arr[1])
const bytesLength = bytes.length
const u8arr = new Uint8Array(bytesLength)
for (let i = 0; i < bytes.length; i++) {
u8arr[i] = bytes.charCodeAt(i)
}
const blob = new Blob([u8arr], { type: mime })
// 回调函数 根据需求返回二进制数据或者base64数据,我的项目都给返回了
callback(blob, base64)
}
},
图片旋转
//图片旋转
rotateImg(img, direction, canvas) {
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
//var img = document.getElementById(pid);
if (img == null)return;
var height = canvas.height;
var width = canvas.width;
//var step = img.getAttribute('step');
var step = 2;
if (step == null) {
step = min_step;
}
if (direction == 'right') {
step++;
//旋转到原位置,即超过最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
//旋转角度以弧度值为参数
var degree = step * 90 * Math.PI / 180;
var ctx = canvas.getContext('2d');
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height, width, height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height, width, height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0, width, height);
break;
}
},
上传图片服务器
//上传图片服务器
gotoService(blob, base64){
if (blob.size >= 2*1024*1024) {
Toast('图片不得大于2M')
return
} else {
var param = new FormData()
param.append('file', blob, '.jpg')
param.append('filename', blob + '.jpg')
param.append('type', '1')
let that = this
//下面是用axios上传图片至服务器 根据自定义的项目api上传至服务器即可
onUpload(param).then(res => {
if (res.code == 200) {
that.images.push(res.data)
} else {
Toast({message:'上传失败'), duration: 2000})
}
})
}
},
到这里上传图片中的问题就都解决了,压缩图片,旋转图片 ,上传图片
如有不足,欢迎各位指导
本文转自 https://www.jianshu.com/p/294c7c3ad413, 如有侵权,请联系删除。