失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > vue之原生上传图片并压缩图片大小(1)

vue之原生上传图片并压缩图片大小(1)

时间:2020-09-25 07:39:31

相关推荐

vue之原生上传图片并压缩图片大小(1)

vue之上传图片并压缩图片大小

vue之上传图片并压缩图片大小

vue之上传图片并压缩图片大小

这里使用的是compressorjs, 安装npm i compressorjs

注意:这个插件是利用canvas对图片进行重绘,如果压缩太过的话,会导致一定程度上的图片失真。

compressorjs官网

主要代码如下:

<div class="van-uploader__upload"><i class="van-icon van-icon-photograph van-uploader__upload-icon"></i><input type="file" multiple accept="image/*" @change="handleImgUpload($event, item)"/></div><style lang="scss">.van-uploader__upload {display: none;}</style>

<script>import Compressor from 'compressorjs';export default {methods: {async handleImgUpload(e, item) {if (!e.target.files || !e.target.files.length) {return}const files = e.target.filesif (files.length > 9) {this.$toast('一次最多上传9张,请分批次上传!')e.target.value = ''return}$loading.show()files.forEach(async (file, index) => {if (!file.name || !file.type.includes('image/')) {this.$toast('上传失败,只能上传照片!')// 上传完成if (index === files.length - 1) {//清空上传控件的值,防止不能重复上传e.target.value = ''$loading.hide()}return //forEach里的return相当于continue}if (file.size > 1024 * 1024 * 10) {this.$toast('文件太大,不能超过10M!')// 上传完成if (index === files.length - 1) {//清空上传控件的值,防止不能重复上传e.target.value = ''$loading.hide()}return}try {let formData = new FormData()// 大于512k则先压缩if (file.size > 512 * 1024) {const compressorFile = await pressor(file)formData.append('file', compressorFile, compressorFile.name)} else {formData.append('file', file, file.name)}const res = await imgUpload(formData)if (res.code === 0 && res.item) {item.answer.push({url: res.item,})} else {this.$toast('上传失败,请稍后重试!')}} catch (error) {this.$toast('上传失败,请稍后重试!')console.error(error)}// 上传完成if (index === files.length - 1) {//清空上传控件的值,防止不能重复上传e.target.value = ''$loading.hide()}})},// 压缩async compressor(file) {return new Promise(resolve => {new Compressor(file, {quality: 0.2,success: resolve,error(err) {console.log(err.message)},})})},} } </script>

代码片段如下:

<template><div><div class="scroll-wrapper" v-if="taskInfo"><template v-if="taskInfo.fileUrls && taskInfo.fileUrls.length"><divclass="ml63 flex-center mt10 fs14"v-for="(item, idx) in taskInfo.fileUrls":key="idx"><div class="icon-file mr12"><img src="@/assets/img/icon-file@2x.png" alt="" /></div><div class="task-file mw25 ellipse">{{item.fileName }}</div><div class="btn flex-center-center ml40"><a :href="item.fileUrl">预览</a></div><div class="btn flex-center-center ml32"><a :href="item.fileUrl">下载</a></div></div></template><div class="task-detail"><div class="task-caption" v-for="(item, idx) in questions" :key="idx"><!-- 图片上传 --><div class="flex mt20" v-if="item.questionType === 4"><div class="van-uploader__wrapper" :class="{ 'task-img': isDisabled }"><div class="van-uploader__preview" v-for="(img, imgIdx) in item.answer" :key="imgIdx"><div class="van-image van-uploader__preview-image" @click="handlePreview(item.answer, imgIdx)"><img class="van-image__img" :src="img.url" style="object-fit: cover"/></div><div v-if="!isDisabled" class="van-uploader__preview-delete" @click="item.answer.splice(imgIdx, 1)"><i class="van-icon van-icon-cross van-uploader__preview-delete-icon"></i></div></div><div class="van-uploader__upload" v-if="!isDisabled"><i class="van-icon van-icon-photograph van-uploader__upload-icon"></i><input type="file" multiple accept="image/*" @change="handleImgUpload($event, item)" class="van-uploader__input"/></div></div></div><!-- 附件上传 --><div class="mt20 file-upload" v-if="item.questionType === 5"><div class="flex file-item" v-for="(file, fileIdx) in item.answer" :key="fileIdx"><div class="file-left"><div class="icon-file mr12"><img src="@/assets/img/icon-file@2x.png" alt="" class="" /></div><div class="task-file file-name ellipse">{{file.fileName }}</div></div><div class="task-file ml40" v-if="!isDisabled"><span @click="removeFile(item, fileIdx)">删除</span></div><div class="ml20 task-file flex-center-center" v-else><div class="btn flex-center-center"><a :href="file.fileUrl">预览</a></div><div class="btn flex-center-center ml32"><a :href="file.fileUrl">下载</a></div></div></div><van-button color="#4646E6" class="mt40 ml40" @click="handleFileClick('file' + idx)" :disabled="isDisabled"><div class="flex-center fs14"><input :id="'file' + idx" type="file" style="display: none" @change="handleFileUpload($event, item)"/><div class="file-icon mr12"><img src="@/assets/img/icon-file_upload@2x.png" /></div>附件上传</div></van-button></div></div></div></div></div></template><script>import {getTaskDetail, imgUpload, fileUpload, userExecute } from '@/api/myTask'import {ImagePreview } from 'vant'import Compressor from 'compressorjs'const fileExtensions = ['xlsx', 'xls', 'docx', 'doc', 'pdf']export default {name: 'index',components: {},props: {},data() {return {id: this.$route.params.id,from: this.$route.query.from,shareAccount: this.$route.query.shareAccount,taskInfo: null,questions: [],currentItem: null,imgList: [],}},mounted() {this.getTaskDetail(this.id)},methods: {async getTaskDetail(id) {try {$loading.show()const data = {id }if (this.from === 'behalfTask') {data.userAccountId = this.shareAccount}const res = await getTaskDetail(data)$loading.hide()if (res.code === 0) {this.taskInfo = res.itemthis.initQuestions(this.taskInfo.taskItem)}} catch (error) {$loading.hide()console.error(error)}},initQuestions(taskItem) {for (const item of taskItem) {let question = {}question.itemId = item.itemIdquestion.title = item.titlequestion.questionDescribe = (item.questionDescribe && '(' + item.questionDescribe + ')') || ''question.questionType = item.questionTypequestion.required = item.requiredquestion.options = item.itemContent// 处理问题答案switch (item.questionType) {// 图片上传case 4:if (item.itemExecute && item.itemExecute.taskItemExecute) {question.answer = item.itemExecute.taskItemExecute.split(',').map(img => {return {url: img }})} else {question.answer = []}break// 附件上传case 5:if (item.itemExecute && item.itemExecute.taskItemExecute) {question.answer = item.itemExecute.taskItemExecute.split(',').map(file => {if (file.split('&').length === 2) {return {fileUrl: file.split('&')[0],fileName: file.split('&')[1],}}return {fileUrl: '', fileName: '' }})} else {question.answer = []}break}this.questions.push(question)}},// 点击事件handleFileClick(el) {document.getElementById(el).click()},// 附件上传async handleFileUpload(e, item) {if (!e.target.files || !e.target.files.length) {return}if (!e.target.files[0].name || e.target.files[0].name.split('.').length < 2) {this.$toast('无效文件!')return}if (!fileExtensions.includes(e.target.files[0].name.split('.')[1].toLowerCase())) {this.$toast.fail('请选择附件文件类型')return}if (e.target.files[0].size > 1024 * 1024 * 10) {this.$toast.fail('文件太大,不能超过10M!')return}try {const res = await fileUpload({file: e.target.files[0] })// 清空上传控件的值,防止不能重复上传e.target.value = ''if (res.code === 0) {item.answer.push({fileName: res.item.fileName,fileUrl: res.item.fileUrl,})}} catch (error) {e.target.value = ''console.error(error)}},// 图片上传async handleImgUpload(e, item) {if (!e.target.files || !e.target.files.length) {return}const files = e.target.filesif (files.length > 5) {this.$toast('一次最多上传5张,请分批次上传!')e.target.value = ''return}$loading.show()files.forEach(async (file, index) => {if (!file.name || !file.type.includes('image/')) {this.$toast('上传失败,只能上传照片!')// 上传完成if (index === files.length - 1) {//清空上传控件的值,防止不能重复上传e.target.value = ''$loading.hide()}return //forEach 里的 return 相当于 continue}if (file.size > 1024 * 1024 * 10) {this.$toast('文件太大,不能超过10M!')// 上传完成if (index === files.length - 1) {//清空上传控件的值,防止不能重复上传e.target.value = ''$loading.hide()}return}try {let formData = new FormData()// 大于512k则先压缩if (file.size > 512 * 1024) {const compressorFile = await pressor(file)formData.append('file', compressorFile, compressorFile.name)} else {formData.append('file', file, file.name)}const res = await imgUpload(formData)if (res.code === 0 && res.item) {// 给item 添加图片路径item.answer.push({url: res.item,})} else {this.$toast('上传失败,请稍后重试!')}} catch (error) {this.$toast('上传失败,请稍后重试!')console.error(error)}// 上传完成if (index === files.length - 1) {//清空上传控件的值,防止不能重复上传e.target.value = ''$loading.hide()}})},// 图片压缩async compressor(file) {return new Promise(resolve => {new Compressor(file, {quality: 0.2,success: resolve,error(err) {console.log(err.message)},})})},// 图片预览handlePreview(imgList, startPosition) {ImagePreview(imgList.map(item => item.url),startPosition)},// 附件删除removeFile(ques, fileIdx) {this.$dialog.confirm({message: `是否删除附件“${ques.answer[fileIdx].fileName}”` }).then(() => {ques.answer.splice(fileIdx, 1)}).catch(() => {})},},computed: {isDisabled() {return (// 直接进入此页面的只允许查看!this.from ||//从执行记录进来的只允许查看this.from === 'executeRecord' ||//代执行却没有代执行人的ID不允许执行(this.from === 'behalfTask' && !this.shareAccount) ||//已执行任务不允许再执行this.taskInfo.execStatus === 1 ||//不允许超期执行且已超期则不允许执行(!this.taskInfo.allowOverDue && !!this.taskInfo.overdueFlag))},},}</script>

上传代码部分感谢龙哥的帮忙和指导;

其中接口调接口写法

import request from '@/utils/request'import store from '@/store'function addParams(params) {if (!params.userAccountId) {params.userAccountId = store.getters.userAccountID}}// 图片上传export function imgUpload(data = {}) {// addParams(data)// let postBody = new FormData()// for (const key in data) {// postBody.append(key, data[key])// }return request({url: '/api/image/upload',method: 'post',data})}// 附件上传export function fileUpload(data = {}) {addParams(data)let postBody = new FormData()for (const key in data) {postBody.append(key, data[key])}return request({url: '/api/file/upload',method: 'post',data: postBody})}

注意点:

选择图片时,需要清空一下这个值,防止同一张图片不让多次选择上传;

e.target.value = ''

其他写法:

<template><div class="ele-upload-styl"><!-- <el-uploadaction="":headers="uploadProps.headers":show-file-list="false":http-request="fnUploadRequest":on-success="handleSuccess":before-upload="handleUpload"accept=".png,.jpg,.jpeg,.gif,.webp"multiple:limit="5":on-exceed="handleExceed"ref="upload"><div class="img-cont pr"><img slot="trigger" class="img-icon" src="@/assets/img/icon-img-upload.png" alt=""><span slot="tip" class="img-text">图片</span></div></el-upload> --><-- 原生写法--><label for="myFile"><inputtype="file"multipleaccept="image/*"id="myFile"@change="handleImgUpload($event)"style="display: none"/><div class="img-cont pr"><imgslot="trigger"class="img-icon"src="@/assets/img/icon-img-upload.png"alt=""/><span slot="tip" class="img-text">图片</span></div></label></div></template><script>import {getAccessToken,getRefreshToken,getAccessTokenTTL} from '@/utils/auth'import {uploadOSS } from '@/utils/ossImage'export default {name: 'imgUpload',components: {},props: {},computed: {userAccountID() {return this.$store.state.user.userAccountID},uploadProps() {return {// action: `${process.env.VUE_APP_BASE_API}/api/image/upload`,headers: {// 接口可能要带token: "",Authorization: getAccessToken()},data: {}}}},data() {return {}},methods: {// handleExceed(file, fileList) {// // console.log(file, fileList);// this.$message.error("上传失败,限制上传数量10张图片以内!");// },// beforeUpload_u(file, fileList) {// // console.log(file, fileList);// var testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);// const extension =//testmsg === "png" ||//testmsg === "jpg" ||//testmsg === "jpeg" ||//testmsg === "gif" ||//testmsg === "webp";// const isLimit10M = file.size / 1024 / 1024 < 10;// var bool = false;// if (extension && isLimit10M) {//bool = true;// } else {//bool = false;// }// if (!extension) {//this.$message.error("请上传图片格式文件!");//return bool;// }// if (!isLimit10M) {//this.$message.error("上传失败,不能超过10M!");//return bool;// }// return bool;// },// handleSuccess(res) {// // console.log(res);// if (res.code == 0) {//this.$emit("imgData", res.item);//this.$message.success("上传图片成功!");// } else {//this.$message.error("上传图片失败!");// }// },// handleError(err) {// this.$message.error("上传图片失败!");// },// 上传图片判断handleUpload(file) {// console.log(file);var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)const extension =testmsg.toLowerCase() === 'png' ||testmsg.toLowerCase() === 'jpg' ||testmsg.toLowerCase() === 'jpeg' ||testmsg.toLowerCase() === 'gif' ||testmsg.toLowerCase() === 'webp'const isLimit10M = file.size / 1024 / 1024 < 10var bool = falseif (extension && isLimit10M) {bool = true} else {bool = false}if (!extension) {this.$message.error('请上传图片格式文件!')return bool}if (!isLimit10M) {this.$message.error('文件太大,单个文件不能超过10M! ')return bool}return bool},handleExceed(files, fileList) {// console.log(files, fileList);this.$message.warning(` 一次最多上传5张,请分批次上传! `)},// 上传图片async fnUploadRequest(options) {// console.log(options);try {this.$loading.show()// console.log(options);let file = options.file // 拿到 filelet res = await uploadOSS(file)// console.log(res);// 返回的就是图片地址this.$emit('imgData', res)this.$loading.hide()} catch (e) {this.$loading.hide()this.$message.error('上传图片失败!请重新上传')}},//图片上传成功回调handleSuccess(res) {// console.log(res);this.$refs.upload.clearFiles() //清空选择列表if (res) {this.$emit('imgData', res)}},// 原生的方法 触发调接口,其他操作自行研究handleImgUpload(e) {console.log(e.target.files)e.target.files.forEach(async (file) => {console.log(file)try {this.$loading.show()let res = await uploadOSS(file)// console.log(res);// 返回的就是图片地址this.$emit('imgData', res)this.$loading.hide()} catch (e) {this.$loading.hide()this.$message.error('上传图片失败!请重新上传')}})e.target.value = ''}}}</script><style lang="scss" scoped>::v-deep .el-upload,::v-deep .el-upload--picture-card {// width: 50px;height: 24px;border: none;line-height: 0;display: block;background: #f5f6fb;}::v-deep .el-upload {width: 50px;}.img-cont {width: 50px;height: 24px;background: #f5f6fb;.img-icon {color: #ccc;}.img-text {font-size: 12px;height: 24px;color: #000;margin-left: 3px;}}</style>

如果觉得《vue之原生上传图片并压缩图片大小(1)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。