思路:拿到图片之后,转为 base64格式,然后用EXIF解决旋转的问题,再将base64格式的文件传给七牛云,返回url。
七牛云base64文件上传参考文档: https://developer.qiniu.com/kodo/kb/1326/how-to-upload-photos-to-seven-niuyun-base64-code
<template>
<div>
<div class="weui-gallery" v-bind:class="{showgallery: showgallery}">
<span
class="weui-gallery__img"
@click="closeGallery"
:style="{backgroundImage:'url('+galleryimgUrl+')'}"
></span>
<div class="weui-gallery__opr">
<a href="javascript:" class="weui-gallery__del" @click="delGallery">
<i class="weui-icon-delete weui-icon_gallery-delete"></i>
</a>
</div>
</div>
<div class="weui-cell">
<div class="weui-uploader">
<div class="weui-uploader__hd">
<p class="weui-uploader__title">图片上传</p>
<div class="weui-uploader__info">{{uploadNum}}/{{allUploadNum}}</div>
</div>
<div class="weui-uploader__bd">
<ul class="weui-uploader__files" id="uploaderFiles">
<li
v-for="(item,index) in imgArr"
:key="index"
:style="{backgroundImage:'url('+item.src+')'}"
@click="openGallery(index)"
class="weui-uploader__file weui-uploader__file_status"
>
<div class="weui-uploader__file-content">
<i
:class="[item.uploadimg == 0 ? 'weui-loading' : (item.flag == 1 ? 'weui-icon-success' : 'weui-icon-warn')]"
></i>
</div>
</li>
<!--<li class="weui-uploader__file weui-uploader__file_status">
<div class="weui-uploader__file-content">
<div class="weui-loading"></div>
</div>
</li>-->
</ul>
<div class="weui-uploader__input-box" v-show="showUploadBtn">
<input
id="uploaderInput"
class="weui-uploader__input"
v-on:change="uploadImg"
type="file"
accept="image/*"
multiple
/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios"
import EXIF from "exif-js"
export default {
name: "TestContent",
props: {
maxImgUploadNum: {
type: Number
}
},
data() {
return {
//所有图片列表
imgArr: [],
//是否显示 gallery
showgallery: false,
//gallery当前的图片地址
galleryimgUrl: "",
//当前点击的图片地址索引
currentImgIndex: -1,
//一共可以上传多少张图片
allUploadNum: this.maxImgUploadNum,
//已经上传的图片数量
uploadNum: 0,
//是否显示上传按钮,当大于最大上传数量的时候,隐藏,否则显示
showUploadBtn: true,
//每次添加图片给一个特定的id值,默认为1
uploadid: 1
}
},
watch: {
imgArr: function() {
this.uploadNum = this.imgArr.length
if (this.imgArr.length > this.allUploadNum) {
this.imgArr = this.imgArr.slice(0, this.allUploadNum)
this.$weui.toast("只能添加" + this.allUploadNum + "张图片")
}
// 触发事件,把imgArr的值返回给调用父级
this.$emit('getImgArrList', this.imgArr)
//当图片达到允许最大上传值 等于大于的时候,则隐藏
if (this.imgArr.length >= this.allUploadNum) {
this.showUploadBtn = false
} else {
this.showUploadBtn = true
}
}
},
mounted () {
console.log(this.maxImgUploadNum)
},
methods: {
//测试最新的方法
uploadImg(e) {
let tag = e.target
let fileList = tag.files
let imgNum = fileList.length
// 这里要注意,如果选择的图片加上已经存在的图片数量大于最大上传的数量,只能上传最大数量,然后提示打到达最大的数量
let nowUploadNum = fileList.length + this.imgArr.length
if (nowUploadNum > this.allUploadNum) {
// 如果已经存在的数量加上上传的数量大于 最大上传数量, 则上传 最大上传数量 - 实际存在的数量
let trueUplaodNum = this.allUploadNum - this.imgArr.length
if (trueUplaodNum > 0) {
// 如果实际上传数量大于0, 说明还需上传
this.uploadImgEvent(trueUplaodNum, fileList)
} else {
// 如果实际上传数量 不大于 0, 说明已经是最大上传数量,不上传,直接提示 已经是最大数量
this.$weui.alert("最大只能上传" + this.allUploadNum + "张")
}
} else {
//如果现在要上传的数量加上一句存在的图片数量 小于 最大上传数量,则直接上传
this.uploadImgEvent(fileList.length, fileList)
}
},
//处理函数
uploadImgEvent(imgNum, fileList) {
let loading = this.$weui.loading('上传中...')
let Orientation
const _this = this
for (let i = 0; i < imgNum; i++) {
let fileSize = fileList[i].size
EXIF.getData(fileList[i], function() {
Orientation = EXIF.getTag(fileList[i], "Orientation")
});
let reader = new FileReader()
reader.readAsDataURL(fileList[i])
reader.onload = function() {
var oReader = new FileReader()
oReader.onload = function(e) {
var image = new Image()
image.src = e.target.result
image.onload = function() {
var expectWidth = this.naturalWidth
var expectHeight = this.naturalHeight
if (
this.naturalWidth > this.naturalHeight &&
this.naturalWidth > 600
) {
expectWidth = 600
expectHeight =
(expectWidth * this.naturalHeight) /
this.naturalWidth
} else if (
this.naturalHeight > this.naturalWidth &&
this.naturalHeight > 1000
) {
expectHeight = 1000
expectWidth =
(expectHeight * this.naturalWidth) /
this.naturalHeight
}
var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
canvas.width = expectWidth
canvas.height = expectHeight
ctx.drawImage(
this,
0,
0,
expectWidth,
expectHeight
)
var base64 = null
//修复ios上传图片的时候 被旋转的问题
if (Orientation != "" && Orientation != 1) {
switch (Orientation) {
case 6: //需要顺时针(向左)90度旋转
_this.rotateImg(this, "left", canvas)
break
case 8: //需要逆时针(向右)90度旋转
_this.rotateImg(this, "right", canvas)
break
case 3: //需要180度旋转
_this.rotateImg(this, "right", canvas) //转两次
_this.rotateImg(this, "right", canvas)
break
}
}
base64 = canvas.toDataURL("image/jpeg", 0.95)
let uploadid = _this.uploadid + 1
_this.uploadid = _this.uploadid + 1
//清除加载层
loading.hide()
if (fileList[i].size / 1024000 > 1) {
//大于1的情况下,把处理放在下面的函数中处理
_this.imgScale(base64, 3, uploadid, fileSize)
} else {
//小于1的情况下,用下面的办法处理
_this.imgArr.push({ src: base64, flag : 0, uploadimg: 0, uploadid: uploadid })
//上传到七牛云,上传成功修改 imgArr 状态
_this.putb64(_this.getBase64Str(base64), uploadid, fileSize)
}
}
}
oReader.readAsDataURL(fileList[i])
}
}
},
getBase64Str (str_base64){
let arr_str = str_base64.split(',')
if(arr_str.length == 2 && arr_str[1]){
return arr_str[1]
}else{
return 0
}
},
imgScale(imgUrl, quality, uploadid, fileSize) {
let img = new Image()
let _this = this
let canvas = document.createElement("canvas")
let cxt = canvas.getContext("2d")
img.src = imgUrl
img.onload = function() {
//缩放后图片的宽高
let width = img.naturalWidth / quality
let height = img.naturalHeight / quality
canvas.width = width
canvas.height = height
cxt.drawImage(this, 0, 0, width, height)
let base64 = canvas.toDataURL("image/jpeg")
_this.imgArr.push({ src: base64, flag: 0, uploadimg: 0, uploadid: uploadid })
//上传到七牛云,上传成功修改 imgArr 状态
_this.putb64(_this.getBase64Str(base64), uploadid, fileSize)
}
},
//图片旋转
rotateImg(img, direction, canvas) {
var min_step = 0
var max_step = 3
if (img == null) return
var height = img.height
var width = img.width
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)
break
case 1:
canvas.width = height
canvas.height = width
ctx.rotate(degree)
ctx.drawImage(img, 0, -height)
break
case 2:
canvas.width = width
canvas.height = height
ctx.rotate(degree)
ctx.drawImage(img, -width, -height)
break
case 3:
canvas.width = height
canvas.height = width
ctx.rotate(degree)
ctx.drawImage(img, -width, 0)
break
}
},
//base64 提交到 七牛云
putb64(str_base64, uploadid, fileSize) {
//获取七牛云token
let postData = {
'uploadid' : uploadid
}
const qs = require('qs')
const that = this
axios.post(this.common.HTTPHOST+"/api/qiniu/getToken", qs.stringify(postData), {
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(function(res){
let retData = res.data
if(retData.ret == 1){
//获取成功
let token = retData.data.token
let pic = str_base64
// let url = "http://upload-z1.qiniup.com/putb64/" + fileSize
let url = "http://up-z1.qiniup.com/putb64/-1"
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
let uploadid = res.data.data.uploadid
that.imgArr.forEach((item, index, array) => {
if(item.uploadid == uploadid){
if (xhr.readyState == 4) {
that.imgArr[index]['flag'] = 1 //上传成功
that.imgArr[index]['uploadimg'] = 1 //完成上传
}
}
})
}
xhr.open("POST", url, true)
xhr.setRequestHeader("Content-Type", "application/octet-stream")
xhr.setRequestHeader("Authorization", 'UpToken ' + token)
xhr.send(pic)
}else{
//获取失败
that.imgArr.forEach((item, index, array) => {
if(item.uploadid == uploadid){
that.imgArr[index]['flag'] = 0 //上传失败
that.imgArr[index]['uploadimg'] = 1 //完成上传
}
})
// that.$weui.alert('网络错误')
}
}).catch(function(err){
//获取失败
that.imgArr.forEach((item, index, array) => {
if(item.uploadid == uploadid){
that.imgArr[index]['flag'] = 0 //上传失败
that.imgArr[index]['uploadimg'] = 1 //完成上传
}
})
// that.$weui.alert('网络错误')
console.log(err)
})
},
//打开 gallery
openGallery(index) {
this.currentImgIndex = index
this.galleryimgUrl = this.imgArr[index]["src"]
this.showgallery = true
},
//删除gallery
delGallery() {
const that = this
if (this.currentImgIndex > -1) {
//如果当前索引大于0,说明存在
this.imgArr.splice(this.currentImgIndex, 1)
this.currentImgIndex = -1
}
that.$weui.toast("删除成功", {
duration: 1000,
callback: function() {
that.showgallery = false
}
});
},
//关闭gllery
closeGallery() {
this.showgallery = false
}
}
};
</script>
<style lang="stylus" scoped>
.showgallery {
display: block;
}
</style>