奇淼(piexlmax
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 235 additions and 19 deletions
-
100web/src/components/upload/image.vue
-
99web/src/utils/image.js
-
55web/src/view/example/upload/upload.vue
@ -0,0 +1,100 @@ |
|||
<!-- |
|||
<div> |
|||
带压缩的上传 |
|||
<upload-image v-model="imageUrl" :fileSize="512" /> |
|||
已上传文件 {{ imageUrl }} |
|||
</div> |
|||
|
|||
|
|||
--> |
|||
|
|||
<template> |
|||
<div> |
|||
<el-upload |
|||
class="image-uploader" |
|||
:action="`${path}/fileUploadAndDownload/upload`" |
|||
:show-file-list="false" |
|||
:on-success="handleImageSuccess" |
|||
:before-upload="beforeImageUpload" |
|||
:multiple="false" |
|||
> |
|||
<img v-if="imageUrl" :src="imageUrl" class="image" /> |
|||
<i v-else class="el-icon-plus image-uploader-icon"></i> |
|||
</el-upload> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
const path = process.env.VUE_APP_BASE_API; |
|||
import ImageCompress from "@/utils/image.js"; |
|||
export default { |
|||
name: "upload-image", |
|||
model: { |
|||
prop: "imageUrl", |
|||
event: "change", |
|||
}, |
|||
props: { |
|||
imageUrl: { |
|||
type: String, |
|||
default: "", |
|||
}, |
|||
fileSize: { |
|||
type: Number, |
|||
default: 2048, // 2M 超出后执行压缩 |
|||
}, |
|||
maxWH: { |
|||
type: Number, |
|||
default: 1920, // 图片长宽上限 |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
path: path, |
|||
}; |
|||
}, |
|||
methods: { |
|||
beforeImageUpload(file) { |
|||
let isRightSize = file.size / 1024 < this.fileSize; |
|||
if (!isRightSize) { |
|||
// 压缩 |
|||
let compress = new ImageCompress(file, this.fileSize, this.maxWH); |
|||
return compress.compress(); |
|||
} |
|||
return isRightSize; |
|||
}, |
|||
handleImageSuccess(res, file) { |
|||
// this.imageUrl = URL.createObjectURL(file.raw); |
|||
const { code, msg, data } = res; |
|||
if (data.file) { |
|||
this.$emit("change", data.file.url); |
|||
} |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.image-uploader { |
|||
border: 1px dashed #d9d9d9; |
|||
width: 180px; |
|||
border-radius: 6px; |
|||
cursor: pointer; |
|||
position: relative; |
|||
overflow: hidden; |
|||
} |
|||
.image-uploader { |
|||
border-color: #409eff; |
|||
} |
|||
.image-uploader-icon { |
|||
font-size: 28px; |
|||
color: #8c939d; |
|||
width: 178px; |
|||
height: 178px; |
|||
line-height: 178px; |
|||
text-align: center; |
|||
} |
|||
.image { |
|||
width: 178px; |
|||
height: 178px; |
|||
display: block; |
|||
} |
|||
</style> |
@ -0,0 +1,99 @@ |
|||
export default class ImageCompress { |
|||
constructor(file, fileSize, maxWH = 1920) { |
|||
this.file = file |
|||
this.fileSize = fileSize |
|||
this.maxWH = maxWH // 最大长宽
|
|||
} |
|||
|
|||
compress() { |
|||
// 压缩
|
|||
const fileType = this.file.type |
|||
const fileSize = this.file.size / 1024 |
|||
return new Promise(resolve => { |
|||
const reader = new FileReader(); |
|||
reader.readAsDataURL(this.file); |
|||
reader.onload = () => { |
|||
const canvas = document.createElement('canvas'); |
|||
const img = document.createElement('img'); |
|||
img.src = reader.result; |
|||
img.onload = () => { |
|||
const ctx = canvas.getContext('2d'); |
|||
let _dWH = this.dWH(img.width, img.height, this.maxWH) |
|||
canvas.width = _dWH.width |
|||
canvas.height = _dWH.height |
|||
|
|||
// 清空后, 重写画布
|
|||
ctx.clearRect(0, 0, canvas.width, canvas.height) |
|||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height) |
|||
|
|||
let newImgData = canvas.toDataURL(fileType, 0.90) |
|||
|
|||
// 压缩宽高后的图像大小
|
|||
let newImgSize = this.fileSizeKB(newImgData) |
|||
|
|||
if (newImgSize > this.fileSize) { |
|||
console.log('图片尺寸太大!' + fileSize + " >> " + newImgSize) |
|||
reject(`图片尺寸太大!`) |
|||
} |
|||
|
|||
let blob = this.dataURLtoBlob(newImgData, fileType) |
|||
let nfile = new File([blob], this.file.name); |
|||
resolve(nfile) |
|||
}; |
|||
}; |
|||
}); |
|||
} |
|||
|
|||
/* |
|||
* 长宽等比缩小 |
|||
* 图像的一边(长或宽)为最大目标值 |
|||
* */ |
|||
dWH(srcW, srcH, dMax) { |
|||
|
|||
let defaults = { |
|||
width: srcW, |
|||
height: srcH |
|||
} |
|||
if (Math.max(srcW, srcH) > dMax) { |
|||
if (srcW > srcH) { |
|||
defaults.width = dMax |
|||
defaults.height = Math.round(srcH * (dMax / srcW)) |
|||
return defaults |
|||
} else { |
|||
defaults.height = dMax |
|||
defaults.width = Math.round(srcW * (dMax / srcH)) |
|||
return defaults |
|||
} |
|||
} else { |
|||
return defaults |
|||
} |
|||
} |
|||
|
|||
fileSizeKB(dataURL) { |
|||
let self = this |
|||
|
|||
let sizeKB = 0 |
|||
sizeKB = Math.round((dataURL.split(',')[1].length * 3 / 4) / 1024) |
|||
return sizeKB |
|||
} |
|||
|
|||
/* |
|||
* 转为Blob |
|||
* */ |
|||
dataURLtoBlob(dataURL, fileType) { |
|||
let self = this |
|||
|
|||
let byteString = atob(dataURL.split(',')[1]) |
|||
let mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0] |
|||
let ab = new ArrayBuffer(byteString.length) |
|||
let ia = new Uint8Array(ab) |
|||
for (let i = 0; i < byteString.length; i++) { |
|||
ia[i] = byteString.charCodeAt(i) |
|||
} |
|||
if (fileType) { |
|||
mimeString = fileType |
|||
} |
|||
return new Blob([ab], { type: mimeString, lastModifiedDate: new Date() }) |
|||
} |
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue