springboot+vue自定义上传图片及视频

您所在的位置:网站首页 springboot和vue结合怎么看端口 springboot+vue自定义上传图片及视频

springboot+vue自定义上传图片及视频

2024-06-17 01:20| 来源: 网络整理| 查看: 265

说明:本例采用的是将图片视频全都先传到前端,再一次性提交给后端的思路,另外还做了一个上传前的预览

效果图

在这里插入图片描述

vue页面代码 {{ collect_drawer_title }} *产品图片/视频 保存 取消 data数据定义 data() { //这里存放数据 return { //视频展示框是否显示 videoVisible: false, //图片展示框是否显示 dialogVisible: false, //图片展示框对应url dialogImageUrl: undefined, //图片视频文件实际存放数组 pro_files: [], //记录删除前的文件队列 update_src: [], //控制抽屉 collect_drawer: false, //抽屉标题 collect_drawer_title: undefined, //实体类 collect: { collect_id: undefined, note: undefined, price: undefined, url: undefined, source: undefined, seller: undefined, spec: undefined, }, //表单校验 collectRules: {}, }, methods方法定义 methods: { bindBeforeunLoad() { window.onbeforeunload = this.perforresult; }, unBindBeforeunLoad() { window.onbeforeunload = null; }, perforresult() { return ""; }, deleteFile(index) { //由于删除的时候 this.update_src = []; for (var i = index + 1; i this.update_src.push(this.$refs["video" + (i + 1)][0].src); } else { this.update_src.push(this.$refs["image" + (i + 1)][0].src); } } this.pro_files.splice(index, 1); this.$nextTick(() => { for (var j = 0; j if (this.pro_files[i].type === "video") { this.$refs["video" + (i + 1)][0].src = this.update_src[j]; } else { this.$refs["image" + (i + 1)][0].src = this.update_src[j]; } break; } } }); this.$refs.myfile.value = null; }, /**开启全屏loading */ startLoading() { this.loading = this.$loading({ lock: true, text: "加载中...", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.8)", }); }, /**关闭loading**/ closeLoading() { this.loading.close(); }, //用于关闭之后重置视频 resetVideo() { this.$refs.showVideo.pause(); this.videoVisible = false; }, //上传视频方法 uploadMyFile() { const that = this; //获取到 input file let myfile = that.$refs.myfile; //获取到上传的file文件 let file = myfile.files[0]; if (myfile.files[0]) { //判断如果是视频 if (file.type.indexOf("video") != -1) { //先将视频文件放到视频文件总数组 that.$set(that.pro_files, that.pro_files.length, { file: file, type: "video", }); //因为我根据v-for总数组来渲染的,所以当我去设置数组,会有延迟渲染,取不到ref,用nextTick,等渲染结束再操作 that.$nextTick(() => { //获取到当前上传的文件的虚拟dom,用filReader读取文件,并且把视频对应的file信息装填上去。 let video = that.$refs["video" + that.pro_files.length][0]; if (window.FileReader) { var fr = new FileReader(); // fr.onprogress = function (e) { // that.$set( // that.pro_files[that.pro_files.length - 1], // "loaded", // (e.loaded / file.size).toFixed(2) * 100 // ); // }; fr.onloadend = function (e) { //上传完成之后 video.src = e.target.result; video.title = myfile.files[0].name; }; fr.readAsDataURL(myfile.files[0]); } }); } else { //与上传视频几乎同理,不再赘述 that.$set(that.pro_files, that.pro_files.length, { file: file, type: "image", }); that.$nextTick(() => { let image = that.$refs["image" + that.pro_files.length][0]; if (window.FileReader) { var fr = new FileReader(); // fr.onprogress = function (e) { // that.$set( // that.pro_files[that.pro_files.length - 1], // "loaded", // (e.loaded / file.size).toFixed(2) * 100 // ); // }; fr.onloadend = function (e) { image.src = e.target.result; image.title = myfile.files[0].name; }; fr.readAsDataURL(myfile.files[0]); } }); } } }, //预览视频 getPlayer(index) { this.videoVisible = true; this.$nextTick(() => { console.log(window.height); let source = this.$refs["video" + index][0].src; this.$refs.showVideo.src = source; this.$refs.showVideo.play(); }); }, //预览图片 getImage(index) { this.dialogVisible = true; this.$nextTick(() => { let source = this.$refs["image" + index][0].src; this.dialogImageUrl = source; }); }, //打开抽屉 toAddCollect() { this.collect_drawer = true; this.collect_drawer_title = "新增款式"; }, //关闭抽屉 closeDrawer() { this.collect_drawer = false; }, /** * 总体上传方法,思路是使用FormData来封装 * 文件:都在一个数组里,所以循环设置即可,用同一个名字后台好接收 * 表单:使用new Blob将json转成二进制文件 */ saveOrUpdate() { //我这里是因为图片或视频必填 if (this.pro_files.length == 0) { this.$message.error({ message: "产品图片/视频文件不能为空" }); return; } var addData = new FormData(); this.pro_files.forEach((file) => { addData.append("files", file.file); }); addData.append( "productCollect", new Blob([JSON.stringify(this.collect)], { type: "application/json" }) ); //点上传之后打开全屏loading 不让操作 this.startLoading(); //防止用户关闭当前窗口,弹窗防止,如果你想改弹出来的文字说明...(oh,我也想改呢) this.bindBeforeunLoad(); this.postRequest("/api/proCollect", addData, { "Content-Type": "multipart/form-data", }).then((res) => { if (res.success) { this.$message.success({ message: res.message }); this.collect_drawer = false; } this.closeLoading(); this.unBindBeforeunLoad(); }); }, } css样式 ::v-deep .el-upload-list--picture-card .el-upload-list__item { width: 100px; height: 100px; } ::v-deep .el-upload--picture-card { width: 100px; height: 100px; line-height: 110px; } #file_up { background-color: #fbfdff; border: 1px dashed #c0ccda; text-align: center; border-radius: 6px; box-sizing: border-box; width: 130px; height: 130px; line-height: 130px; cursor: pointer; vertical-align: top; display: inline-block; } #file_up:hover, #file_up:focus { border-color: #409eff; color: #409eff; } #file_up i { font-size: 28px; color: #8c939d; } .play-icon { background: grey; font-size: 20px; cursor: pointer; z-index: 100; border-radius: 50%; position: absolute; left: 50%; top: 50%; margin-left: -16px; margin-top: -16px; color: #fff; border: 6px solid grey; } .play-icon:hover { opacity: 0.8; } .video_border { margin-right: 10px; margin-bottom: 10px; } .delete_icon { color: #fff; line-height: inherit; font-size: 17px; cursor: pointer; } .delete_icon:hover { color: #f56c6c; line-height: inherit; font-size: 17px; cursor: pointer; } .delete-div { height: 0px; position: absolute; width: 100%; background: #000; opacity: 0.7; bottom: 0; text-align: center; transition: height 0.2s ease 0s; } .crop:hover .delete-div { height: 30%; } .rect_img { position: absolute; clip: rect(0px 130px 130px 0px); width: 130px; height: 130px; margin-right: 10px; cursor: pointer; object-fit: cover; } 后台接口 @PostMapping @ApiOperation("新增款式收集") public Result addCollect( @RequestPart(value = "productCollect") ProductCollect productCollect, @RequestPart(value = "files", required = true) MultipartFile[] files) { return cProductCollectService.addCollectFlow(productCollect,files); }

记录学习日常,欢迎交流 ~

补充说明

其实我还做了一个进度条,就是你看到注释掉的那些,进度通过 fileReader 类的 onProgress 可以获取到,但效果并不是很理想(而且怪难看的) 这个例子里我没有做任何的文件处理(压缩、分片),可以自行完善 顺便一提,如果有很大的文件,这样上传要卡挺久的,所以我要改成一个个往后端传了,告辞



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3