赞
踩
上传视频的话需要再根据需求更改一下配置文件,更改如下
const fileType=filePath.split('.')[1]
const aliyunFileKey = dir + new Date().getTime() + Math.floor(Math.random() * 150) +`.${fileType}`;
如图所示:
插件地址
安装成功如图所示:
<template> <view> <!-- vant 上传组件,用来图片多选 --> <van-uploader class="upload-border" :accept="accept" :file-list="fileList" :deletable="!disabled" :disabled="disabled" @after-read="_afterRead" @delete="deleteImg" :multiple="true" :max-count="maxCount" :capture="capture" image-fit="none" :upload-icon="uploadIcon" ></van-uploader> <view style="position: absolute;top: -999999px;"> //把canvas移出视窗 <view> <canvas :style="{'width':canvasWidth+'px','height': canvasHeight+'px'}" canvas-id="myCanvas"></canvas> </view> </view> </view> </template> <script> import uploadImage from '@/js_sdk/yushijie-ossutil/ossutil/uploadFile.js'; // 以下路径需根据项目实际情况填写 import { pathToBase64, base64ToPath } from '@/js_sdk/image-tools/index.js'; export default { props: { // 是否禁用 disabled: { type: Boolean, default: false }, // 上传最大张数 maxCount: { type: Number, default: 4 }, // 是否上传至oss isUploaderOss: { type: Boolean, default: false }, // 图片数组 photoList: { type: Array, default: () => [] }, // 图片或者视频选取模式 capture: { type: Array, default: () => { return ['album', 'camera']; } }, // 接受的文件类型, 可选值为all media image file video accept: { type: String, default: 'image' }, // 图片上传到 OSS 服务上的存储目录 ossPathPrefix: { type: String, default: 'yzom_img/APPLET/' }, // 上传图标 uploadIcon: { type: String, default: 'photograph' }, // 是否需要压缩 isCompress: { type: Boolean, default: true }, // 文件上传大小限制,单位 byte compressMaxSize: { type: [Number, String], default: 1024 * 1024 }, // 图片压缩质量,0~100,数值越小,质量越低,压缩率越高 quality: { type: Number, default: 80 }, // 图片是否添加水印 isAddWaterMark: { type: Boolean, default: true } }, data() { return { fileQuality: null, canvasWidth: '', canvasHeight: '' }; }, computed: { fileList: { get() { // console.log('photoList---', this.photoList); return this.photoList; }, set(val) { this.$emit('uploadSuccess', val); } } }, methods: { _afterRead(event) { const { file } = event.detail; // console.log('file---', file); // 图片要进行压缩及添加水印 if (this.accept === 'image') { this.afterRead(file); } else { this.afterReadVideo(file); } }, // 视频上传视频只用进行压缩 async afterReadVideo(file) { const files = []; for (let i = 0; i < file.length; i++) { const ele = file[i]; // files.push(this.addWaterMark(ele.url)); if (this.isCompress) { await this.videoCompress(ele).then(res => { // console.log('压缩返回---', res); files.push(res); }); } else { files.push(ele); } Promise.all(files).then(res => { console.log('返回成功', res); uni.hideLoading(); const that = this; uni.showLoading({ title: '上传中...' }); this.uploadImage(res); }); } }, // 图片上传 async afterRead(file) { const files = []; // console.log(file); this.fileQuality = this.quality; for (let i = 0; i < file.length; i++) { const ele = file[i]; // files.push(this.addWaterMark(ele.url)); if (this.isCompress) { if (this.isAddWaterMark) { // 添加水印返回 await this.addWaterMark(ele.url).then(res => { // console.log('添加水印返回---', res); files.push(res); }); } else { // 压缩返回 await this.imgCompress(ele).then(res => { // console.log('压缩返回---', res); files.push(res); }); } } else { if (this.isAddWaterMark) { await this.addWaterMark(ele.url).then(res => { files.push(res); }); } else { files.push(ele); } } } Promise.all(files).then(res => { // console.log('返回成功', res); uni.hideLoading(); const that = this; uni.showLoading({ title: '上传中...' }); this.uploadImage(res); }); }, // 上传图片 uploadImage(file) { const that = this, uploadPromiseTask = [], // 定义上传的promise任务栈,线上图片 filePromiseTask = []; // 本地图片 this.$emit('afterRead', file); for (let i = 0; i < file.length; i++) { if (this.isUploaderOss) { // push进每一张所需要的上传的图片promise栈 uploadPromiseTask.push(that.uploadFile(file[i].url)); } else { // push进每一张所需要的上传的图片promise栈 uploadPromiseTask.push(file[i]); } } Promise.all(uploadPromiseTask) .then(res => { that.fileList = that.fileList.concat(res); // console.log('fileList', that.fileList); uni.hideLoading(); }) .catch(err => { console.log(err); // 存在有上传失败的文件 uni.hideLoading(); uni.showToast({ title: '上传失败!', icon: 'none' }); }); }, // 上传文件到线上 uploadFile(uploadFile) { return new Promise((resolve, reject) => { const url = 'test'; uploadImage( uploadFile, this.ossPathPrefix + url + '/', // 上传成功 result => { // console.log(result) resolve({ url: result }); }, // 上传失败 result => { uni.showToast({ title: '上传失败', icon: 'none' }); // 这里写上传失败的代码 // console.log(JSON.stringify(result)); } ); }); }, // 删除 deleteImg(event) { const delIndex = event.detail.index, fileList = this.fileList; fileList.splice(delIndex, 1); this.fileList = fileList; this.$emit('uploadSuccess', this.fileList); }, // 相机手动拍照上传 getCamera() { const that = this; uni.chooseImage({ count: that.maxCount, // 最多可以选择的图片张数,默认9 sizeType: ['original', 'compressed'], // original 原图,compressed 压缩图,默认二者都有 sourceType: that.capture, // album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项 // 成功则返回图片的本地文件路径列表 tempFilePaths success: function(res) { const file = res.tempFiles, fileList = []; for (let i = 0; i < file.length; i++) { const element = file[i], params = { url: element.path, size: element.size }; fileList.push(params); } that.afterRead(fileList); } }); }, // 图片压缩 imgCompress(file) { return new Promise((resolve, reject) => { if (file.size > this.compressMaxSize) { this._imgCompress(file, resolve, reject); } else { // console.log('compressMaxSize', file.size > this.compressMaxSize); resolve(file); } }); }, _imgCompress(file, resolve, reject) { uni.showLoading({ title: '正在压缩图片' }); const that = this; uni.compressImage({ src: file.url, quality: that.fileQuality, // 仅对jpg有效 width: '50%', success: res => { // console.log('compressImage', res); // 文件转base64 pathToBase64(res.tempFilePath) .then(base64 => { const imgSize = that.imageSize(base64) * 1024, params = { url: file.url, size: imgSize }; if (imgSize > that.compressMaxSize) { uni.hideLoading(); // console.log('fileQuality', that.fileQuality); if (that.fileQuality < 10) { uni.showToast({ icon: 'none', title: '图片过大,请重新选择', duration: 5000 }); } else { that.fileQuality = (that.fileQuality - 20); that._imgCompress(params, resolve, reject); } } else { uni.showToast({ icon: 'none', title: '压缩成功' }); resolve(params); } console.log('最终图片大小:', imgSize / 1024, 'KB'); }) .catch(error => { console.error(error); uni.showToast({ icon: 'none', title: '转换失败' }); }); }, fail: err => { uni.showToast({ icon: 'none', title: '压缩失败' }); reject(err); }, complete: () => {} }); }, // base64 获取文件大小 imageSize(base64Str) { const tag = 'base64,', indexBase64 = base64Str.indexOf(tag); if (indexBase64 < 0) return -1; const str = base64Str.substr(indexBase64 + tag.length), // 计算文件流大小KB // const size = ((str.length - (str.length / 8) * 2) / 1024).toFixed(2) + 'KB' size = ((str.length * 0.75) / 1024).toFixed(2); return size; }, // 添加水印 addWaterMark(filePath) { return new Promise((resolve, reject) => { const that = this; uni.showLoading({ icon: 'none', title: '正在添加水印' }); uni.getImageInfo({// 获取图片信息 src: filePath, success: res => { that.canvasWidth = res.width; that.canvasHeight = res.height; // var ctx = uni.createCanvasContext('myCanvas'), // 在自定义组件内 需要传递第二参数 this canvas才生效 var ctx = uni.createCanvasContext('myCanvas', this); ctx.clearRect(0, 0, res.width, res.height);// 在给定的矩形内清除指定的像素。 ctx.beginPath();// 起始一条路径,或重置当前路径 ctx.drawImage(filePath, 0, 0, res.width, res.height);// 向画布上面绘制图片 // 为图片添加水印 ctx.translate(0, 0);// 重新映射画布上的 (0,0) 位置 // 这部分是水印的大小位置和数量 let imgWidth = '', imgHeight = ''; if (res.width > res.height) { imgWidth = res.width; imgHeight = res.height; } else { imgWidth = res.height; imgHeight = res.width; } // 水印的字体大小何位置计算 const fonstsize = (imgWidth / 40).toFixed(2), textToWidth = imgWidth / 5 * 0.5, textToHeight = (imgHeight / 8).toFixed(2) * 0.5; // console.log('fonstsize---', fonstsize); // console.log('textToWidth---', textToWidth); // console.log('textToHeight---', textToHeight); // 时间水印 let str = `时间:${new Date()}`, lineWidth = fonstsize, // 文本绘制的初始高度 initHeight = textToHeight, // 绘制文本的高度 titleHeight = 100; // 当前地点水印 str = str + `\r\n定位地点:当前位置`; // 执行的工单类型水印 str = str + `\r\n工单类型:报修工单`; ctx.setFillStyle('#ff0000');// 水印字体颜色 const fontSize1 = (fonstsize < 16 ? 16 : fonstsize); ctx.setFontSize(fontSize1);// 水印字体大小 ctx.setTextAlign('left');// 水印字体位置 var textArray = str.split('\r\n'); // console.log(textArray); // 对水印字符进行转行字符高度等判断(以此适配图片) for (var j = 0; j < textArray.length; j++) { var item = textArray[j], isHeight = that.drawText(ctx, item, initHeight, titleHeight, textToHeight), divideHeight = isHeight.split(','); initHeight = Number(divideHeight[0]) + textToHeight; titleHeight = Number(divideHeight[1]) + textToHeight; } // 开始绘制添加水印的图片并显示在页面中 ctx.draw(false, () => { setTimeout(() => { // canvas转文件 uni.canvasToTempFilePath({ x: 0, y: 0, width: that.canvasWidth, // 画布宽度 height: that.canvasHeight, // 画布高度 destWidth: that.canvasWidth, // 输出图片宽度 destHeight: that.canvasHeight, // 输出图片高度 canvasId: 'myCanvas', fileType: 'jpg', // 目标文件的类型,只支持 'jpg' 或 'png'。默认为 'png' quality: 0.5, // 图片的质量,取值范围为 (0, 1],不在范围内时当作1.0处理(如果不对此进行压缩,会导致图片很大) success: res => { uni.hideLoading(); // 注意此时的地址是加了水印的图片地址(直接url输入浏览器也可以查看包含水印) // console.log('水印添加成功成功---', res); // 文件转base64 pathToBase64(res.tempFilePath) .then(base64 => { const imgSize = that.imageSize(base64) * 1024, params = { size: imgSize, url: res.tempFilePath }; console.log('最终图片大小:', (imgSize / 1024 / 1024).toFixed(2), 'M'); if (that.isCompress) { that.imgCompress(params, resolve, reject).then(res => { resolve(res); }).catch((err) => { reject(err); }); } else { resolve(params); } }) .catch(error => { uni.showToast({ title: '文件转换失败', icon: 'none' }); console.error(error); }); } // }); // 在自定义组件内 需要传递第二参数 this canvas才生效 }, this); }, 500); }); }, fail: (e) => { console.log(e); uni.hideLoading(); uni.showToast({ title: '水印合成失败', icon: 'none' }); } }); }); }, // canvans绘制多行文本,自动转行 /* item:字符串, initHeight:初始高度 */ drawText: function(ctx, item, initHeight, titleHeight, textToHeight) { var lineWidth = 0, // 每次开始截取的字符串的索引 lastSubStrIndex = 0; for (var i = 0; i < item.length; i++) { lineWidth += ctx.measureText(item[i]).width; if (lineWidth > (this.canvasWidth - textToHeight)) { // 绘制截取部分 ctx.fillText(item.substring(lastSubStrIndex, i), textToHeight, initHeight); initHeight += textToHeight; lineWidth = 0; lastSubStrIndex = i; titleHeight += textToHeight; } // 绘制剩余部分 if (i == item.length - 1) { ctx.fillText(item.substring(lastSubStrIndex, i + 1), textToHeight, initHeight); } } // console.log('结束一轮之后的initheight: ' + initHeight + ' titleHeight: ' + titleHeight); return initHeight + ',' + titleHeight; }, // 视频压缩 videoCompress(file) { console.log(file); return new Promise((resolve, reject) => { if (file.size > this.compressMaxSize) { this._videoCompress(file, resolve, reject, 'medium'); } else { // console.log('compressMaxSize', file.size > this.compressMaxSize); resolve(file); } }); }, _videoCompress(file, resolve, reject, quality) { uni.showLoading({ title: '正在压缩视频...' }); var that = this; uni.compressVideo({ src: file.url, quality: quality, // 'low':低,'medium':中,'high':高 success: res => { console.log('压缩后', res); uni.showToast({ title: '视频压缩成功', icon: 'none' }, 2000); console.log('压缩后大小---', res.size / 1024 + 'M'); const params = { url: res.tempFilePath, size: res.size }; // 压缩后的大小仍大于所设大小继续压缩 if ((res.size * 1024) > this.compressMaxSize) { if (quality === 'medium') { that._videoCompress(file, resolve, reject, 'low'); } else { uni.showToast({ icon: 'none', title: '视频太大,请重新选择' }); resolve(params); } } else { resolve(params); } }, fail: err => { uni.showToast({ title: '视频压缩失败', icon: 'none' }, 2000); console.log('error---', err); reject(err); } }); } } }; </script> <style scoped lang="scss"> </style>
代码如下:
<template> <view class="img-test"> 图片上传测试 <uploader-image :ossPathPrefix="'test/yzom_img/APPLET/task_dtl/'" :photoList="phototList" :isUploaderOss="true" :maxCount="3" :ref="oploaderOss" :upload-icon="'photograph'" @uploadSuccess="uploadImageSuccess" /> 视频上传测试 <!-- 上传视频不能超过4M --> <uploader-image :compressMaxSize="1024 * 1024 * 4" :ossPathPrefix="'yzom_img/APPLET/task_dtl/'" :photoList="vidoeList" :isUploaderOss="true" :maxCount="1" :accept="'video'" ref="oploaderOss " :upload-icon="'play-circle'" @uploadSuccess="uploadVideoSuccess" /> </view> </template> <script> import UploaderImage from '@/components/UploaderImage'; export default { name: 'ImgTest', components: { UploaderImage }, data() { return { phototList: [], vidoeList: [] }; }, onLoad() { }, methods: { // 图片上传成功返回 uploadImageSuccess(fileList) { console.log('fileList----', fileList); this.phototList = fileList; }, // 图片上传成功返回 uploadVideoSuccess(fileList) { console.log('fileList----', fileList); this.vidoeList = fileList; } } }; </script> <style scoped lang="scss"> .img-test{ padding:15rpx; } </style>
放大图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。