当前位置: 首页 > news >正文

vue+element+springboot实现多张图片上传

     1.需求说明
     2.实现思路
     3.el-upload组件主要属性说明
     4.前端传递MultipartFile数组与服务端接收说明
     5.完整代码

1.需求说明

    动态模块新增添加动态功能,支持多张图片上传.实现过程中对el-upload组件不是很熟悉,踩了很多坑,当然也参考过别的文章,发现处理很复杂.这里记录最终实现结果,方便有同样问题的同学查看,避免浪费多余时间.下面是发布动态的页面,点击上传图片打开本地文件选择,点击确定完成动态发布功能.
在这里插入图片描述

2.实现思路

    多张图片上传逻辑(兼容单张图片上传,只需要修改最大上传图片数量为1):
    1.需要页面选择好所有图片之后调用服务端的图片上传接口,这样处理的原因是图片上传过程中会出现几种场景:

选择好图片之后要删除之前选择的某一张或某几张;
选择好图片之后要追加几张图片

如果按照选择一张就调用一次图片上传接口,不但会增加服务端调用次数,而且还会增加无效图片的存储成本.
    2.多张图片一次上传接口调用成功后返回多张图片的图片地址,再调用服务端动态发布接口,完成动态发布功能

3.el-upload组件主要属性说明

1.禁用选择图片自动上传功能
    action属性:图片上传服务端请求地址,在组件中属于必传,默认选择一张图片就要调用一次.按照上面梳理的逻辑需要禁用调用该功能,auto-upload设置为false即可.action由于是必传,所以此处设置为#
2.开启多选
    设置multiple设置为true,默认false,否则在出现的文件选择窗口中只能选择一个文件.
3.设置选择文件最大数量
    使用limit属性,超过最大数量的处理逻辑可以在on-exceed中实现,其中处理的逻辑是页面提示已超过最大数请重新选择.
4.显示已选择的图片列表
    设置file-list实现
5.选择好图片之后追加几张图片问题处理
    on-change可以监听选中的图片,一次性选择多个图片会执行多次,但是为保证业务处理逻辑执行成功,只需要最后一次on-change中添加业务处理,所以通过判断监听返回的fileList集合长度是否是最大来处理.自定义的fileList就是on-change中最后一次on-change监听返回的fileList集合信息.下文中自定义的imgUrlList为调用文件上传服务端组装的图片参数集合.服务端的file对象对应on-change监听file中的file.raw.

handleChange(file, fileList){let length = fileList.length	this.maxLength = Math.max(length, this.maxLength)setTimeout(() => {if(length !== this.maxLength) {return} else {this.fileList=fileList}})}

6.选择好图片之后删除已选中图片问题处理
    before-remove可以监听要进行删除的图片信息.每个图片中有一个唯一标识uid,通过唯一标识删除自定义fileList中的图片

handleRemove(file, fileList){this.fileList=this.fileList.filter(imgFile=>imgFile.uid != file.uid)},

4.前端传递MultipartFile[]与服务端接收说明

    服务端接口为post请求,请求方式为post表单提交.具体如下

@PostMapping("/uploadImg")public ResultVo uploadImg(@RequestParam(name = "multipartFiles") MultipartFile[] multipartFiles,@RequestParam(name = "fileType") Integer fileType) {String url = adminDriftService.adminUploadImg(multipartFiles,fileType);return ResultVoUtil.success(url);}

前端页面需要按照FormData类型进行传递,注意一下参数拼接:

let formData = new FormData();this.imgUrlList.map(img=>{formData.append("multipartFiles", img)})formData.append("fileType", 2)

5.完整代码

    前端:
dynamic.js:

export function uploadImg(formData) {return axios({url: 'uploadImg',method: 'POST',	data: formData})
}

新增动态弹窗:

<el-dialog title="新增动态" :visible.sync="addDynamicVisible"><el-form :model="addDynamicForm"><el-form-item label="用户昵称" :label-width="formLabelWidth"><el-select v-model="addDynamicForm.userId" filterable placeholder="请选择"><el-optionv-for="systemUser in systemUserList":key="systemUser.userId":label="systemUser.userName":value="systemUser.userId"></el-option></el-select></el-form-item><el-form-item label="动态文本内容" :label-width="formLabelWidth"><el-input v-model="addDynamicForm.contentText" autocomplete="off"></el-input></el-form-item><el-form-item label="动态图片" :label-width="formLabelWidth"><el-uploadaction="#":file-list="fileList":before-remove="handleRemove":auto-upload="false" :multiple="true" :on-change="handleChange":limit="9":on-exceed="handleExceed"list-type="picture"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div></el-upload></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="closeAddDynamic()">取 消</el-button><el-button type="primary" @click="addDynamicInfo()">确 定</el-button></div></el-dialog><script>			
import {findSystemUserList,addDynamic,uploadImg} from "@/api/dynamic";
export default {data() {return {addDynamicVisible:false, // 是否显示新增动态弹窗addDynamicForm:{}, // 新增动态内容systemUserList:[],  // 系统用户列表信息formLabelWidth: '120px',imgUrlList:[], // 上传文件地址集合fileList:[], // 上传文件本地显示图片集合(非服务器图片地址)maxLength:0 // 上传文件最大值}}methods:{// 图片列表删除之后处理操作handleRemove(file, fileList){this.fileList=this.fileList.filter(imgFile=>imgFile.uid != file.uid)},	// 每次打开本地文件选择窗口选择图片后处理操作		handleChange(file, fileList){let length = fileList.length	this.maxLength = Math.max(length, this.maxLength)setTimeout(() => {if(length !== this.maxLength) {return} else {this.fileList=fileList}})},	// 选择图片超过最大限制9张之后处理操作handleExceed(files, fileList){this.msgError("最多选取9张,请重新选择!")// 清空之前选择内容this.fileList=[]},// 添加动态操作addDynamicInfo(){// 参数校验if(!this.addDynamicForm.userId){this.msgError("请选择用户!")return}this.imgUrlList=this.fileList.map(file=>file.raw)this.serverUploadImg()},	  // 上传图片处理逻辑serverUploadImg() {let formData = new FormData();this.imgUrlList.map(img=>{formData.append("multipartFiles", img)})formData.append("fileType", 2)uploadImg(formData).then(res => {if (res.code === 200) {// 图片上传成功之后触发动态发布逻辑this.addDynamicForm.contentImg=res.datathis.serverAddDynamic()}else {this.msgError(res.msg)}}).catch(() => {this.msgError("请求失败")})},	// 动态发布逻辑serverAddDynamic() {addDynamic(this.addDynamicForm).then(res => {if (res.code === 200) {this.msgSuccess('添加成功!');this.addDynamicVisible=false;this.addDynamicForm={};this.imgUrlList=[];this.fileList=[];this.serverFindDynamicInfoList(this.queryInfo)}else {this.msgError(res.msg)}}).catch(() => {this.msgError("请求失败")})},	  }
</script>		

服务端文件批量上传:

  @ApiImplicitParams({@ApiImplicitParam(name = "multipartFiles",value = "图片集合",required = true, dataType = "MultipartFile[]"),@ApiImplicitParam(name = "fileType",value = "文件类型:1.用户图片:头像以及背景图;2.动态图",required = true,dataType = "Integer",paramType = "insert",example = "1")})@ApiOperation("上传图片")@PostMapping("/uploadImg")public ResultVo uploadImg(@NotNull(message = "文件对象不允许为空!") @RequestParam(name = "multipartFiles") MultipartFile[] multipartFiles,@NotNull(message = "文件类型不允许为空!") @RequestParam(name = "fileType") Integer fileType) {String url = service.adminUploadImg(multipartFiles,fileType);return ResultVoUtil.success(url);}

多张文件上传实现逻辑:

   public String adminUploadImg(MultipartFile[] multipartFiles, Integer fileType) {String imgUrlStr ="";for (int i = 0; i < multipartFiles.length; i++) {String url = aliYunService.uploadImg(multipartFiles[i], fileType,"");imgUrlStr=imgUrlStr+url;if(multipartFiles.length > 1  && i < multipartFiles.length-1){imgUrlStr=imgUrlStr+",";}}return imgUrlStr;}

图片上传具体实现逻辑:

public String uploadImg(MultipartFile multipartFile,Integer fileType,String fileNameParam) {// 返回文件地址String fileUrl = "";// 文件校验checkFile(multipartFile,fileType);// 文件上传路径// modify by txm 2023/3/24 图片类型修改为枚举String filePath = FilePathEnum.getOSSFilePath(fileType);String fileName = StrUtil.isBlank(fileNameParam) ?  multipartFile.getOriginalFilename():fileNameParam;String pathKey = StrUtil.concat(true,filePath,"/",fileName);// meta设置请求头OSS ossClient = new OSSClientBuilder().build(driftConfig.getEndpoint(), driftConfig.getOssAccessKeyId(), driftConfig.getOssAccessKeySecret());try {// 上传至阿里OSSossClient.putObject(driftConfig.getBucketName(), pathKey, new ByteArrayInputStream(multipartFile.getBytes()));fileUrl = driftConfig.getUrlPrefix() + pathKey;} catch (Exception e) {// modify by txm 2023/10/16 修改描述log.error("文件上传失败:{}", e.getMessage());throw new BusinessException("文件上传失败:请重试!");} finally {if (ossClient != null) {ossClient.shutdown();}}// 上传成功return fileUrl;}

相关文章:

vue+element+springboot实现多张图片上传

1.需求说明 2.实现思路 3.el-upload组件主要属性说明 4.前端传递MultipartFile数组与服务端接收说明 5.完整代码 1.需求说明 动态模块新增添加动态功能,支持多张图片上传.实现过程中对el-upload组件不是很熟悉,踩了很多坑,当然也参考过别的文章,发现处理很…...

react使用useState更新数组失败

失败案例&#xff1a; const [addBox, setAddBox] useState([])const itemAdd (item) >{addBox.push(item);setAddBox(addBox)console.log(addBox,点击添加按钮)} 原因&#xff1a;react的useState hook监听的是浅监听 在 React 中&#xff0c;使用 useState Hook 来更新…...

《LIO-SAM阅读笔记》3.后端优化

前言&#xff1a; LIO-SAM后端优化部分写在了mapOptimization.cpp文件中&#xff0c;本部分主要进行了激光帧的scan-to-map匹配&#xff0c;回环检测以及关键帧的因子图优化。本部分主要有两个环节同步进行&#xff0c;一个单独开辟了回环检测线程&#xff0c;另外一个是lidar…...

mac下jd-gui提示没有找到合适的jdk版本

mac下jd-gui提示jdk有问题 背景解决看一下是不是真有问题了方法一&#xff1a;修改启动脚本方法二&#xff1a;设置launchd环境变量 扩展动态切jdk脚本(.bash_profile) 背景 配置了动态jdk后&#xff0c;再次使用JD-GUI提示没有找到合适的jdk版本。 解决 看一下是不是真有问题…...

FlinkSQL窗口实例分析

Windowing TVFs Windowing table-valued functions (Windowing TVFs)&#xff0c;即窗口表值函数 注意&#xff1a;窗口函数不可以单独使用&#xff0c;需要聚合函数&#xff0c;按照 window_start、window_end 分区&#xff0c;即存在&#xff1a;group by window_start,wind…...

18-网络安全框架及模型-信息系统安全保障模型

信息系统安全保障模型 1 基本概念 信息系统安全保障是针对信息系统在运行环境中所面临的各种风险&#xff0c;制定信息系统安全保障策略&#xff0c;设计并实现信息系统安全保障架构或模型&#xff0c;采取工程、技术、管理等安全保障要素&#xff0c;将风险减少至预定可接受的…...

Android 提取(备份)apk(安装包)

Android 提取(备份)apk(安装包) 一、通过安卓代码的方式 主要分三步&#xff1a; 根据应用找到包名根据包名获得apk提取apk 提取apk代码 private static final String BACKUP_PATH "/sdcard/backup1/"; private static final String APK ".apk";pri…...

gRPC-Go基础(4)metadata和超时设置

文章目录 0. 简介1. metadata1.1 metadata结构1.2 metadata创建1.3 客户端处理metadata1.4 服务端处理metadata1.5 metadata的传输 2. 超时设置2.1 客户端输出超时信息2.2 服务端端接收超时信息 3. 小结 0. 简介 Go在多个go routine之间传递数据使用的是Go SDK提供的context包…...

语言模型:从n-gram到神经网络的演进

目录 1 前言2 语言模型的两个任务2.1 自然语言理解2.2 自然语言生成 3 n-gram模型4 神经网络语言模型5 结语 1 前言 语言模型是自然语言处理领域中的关键技术之一&#xff0c;它致力于理解和生成人类语言。从最初的n-gram模型到如今基于神经网络的深度学习模型&#xff0c;语言…...

docker compose 部署 grafana + loki + vector 监控kafka消息

Centos7 随笔记录记录 docker compose 统一管理 granfana loki vector 监控kafka 信息。 当然如果仅仅是想通过 Grafana 监控kafka&#xff0c;推荐使用 Grafana Prometheus 通过JMX监控kafka 目录 1. 目录结构 2. 前提已安装Docker-Compose 3. docker-compose 自定义服…...

kubeadm创建k8s集群

kubeadm来快速的搭建一个k8s集群&#xff1a; 二进制搭建适合大集群&#xff0c;50台以上。 kubeadm更适合中下企业的业务集群。 部署框架 master192.168.10.10dockerkubelet kubeadm kubectl flannelnode1192.168.10.20dockerkubelet kubeadm kubectl flannelnode2192.168.1…...

鸿蒙开发之android对比开发《基础知识》

基于华为鸿蒙未来可能不再兼容android应用&#xff0c;推出鸿蒙开发系列文档&#xff0c;帮助android开发人员快速上手鸿蒙应用开发。 1. 鸿蒙使用什么基础语言开发&#xff1f; ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风…...

2702 高级打字机

因为Undo操作只能撤销Type操作&#xff0c;所以Undo x 实际上就是删除文章末尾x个字母。用一个栈即可解决&#xff08;每个字母最多进出一次&#xff09;。 这种情况下只需要设计一个合理的数据结构依次执行操作即可。 版本树&#xff1a;Undo x撤销最近的x次修改操作&#xf…...

yolov5旋转目标检测-遥感图像检测-无人机旋转目标检测-附代码和原理

综述 为了解决旋转目标检测问题&#xff0c;研究者们提出了多种方法和算法。以下是一些常见的旋转目标检测方法&#xff1a; 基于滑动窗口的方法&#xff1a;在图像上以不同的尺度和角度滑动窗口&#xff0c;通过分类器判断窗口中是否存在目标。这种方法简单直观&#xff0c;…...

Qt学习:Qt的意义安装Qt

Qt 的简介 QT 是一个跨平台的 C图形用户界面应用程序框架。它为程序开发者提供图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正地组件编程。 支持平台 xP 、 Vista、Win7、win8、win2008、win10Windows . Unix/Linux: Ubuntu 等…...

Anylogic Pro 8.8.x for Mac / for Linux Crack

Digital twins – a step towards a digital enterprise AnyLogic是唯一一个支持创建模拟模型的方法的模拟建模工具&#xff1a;面向过程&#xff08;离散事件&#xff09;、系统动态和代理&#xff0c;以及它们的任何组合。AnyLogic提供的建模语言的独特性、灵活性和强大性使…...

ROS无人机初始化GPS定位漂移误差,确保无人机稳定飞行

引言&#xff1a; 由于GPS在室外漂移的误差比较大&#xff0c;在长时间静止后启动&#xff0c;程序发布的位置可能已经和预期的位置相差较大&#xff0c;导致无法完成任务&#xff0c;尤其是气压计的数据不准&#xff0c;可能会导致无人机不能起飞或者一飞冲天。本文主要是在进…...

k8s网络类型

k8s中的通信模式&#xff1a; pod内部之间容器与容器之间的通信。 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间。可以直接通信的。 同一个node节点之内&#xff0c;不同pod之间的通信。 每一个pod都有一个全局的真实的IP地址&#xff0c;同一个n…...

Seata 中封装了四种分布式事务模式,分别是: AT 模式, TCC 模式, Saga 模式, XA 模式,

文章目录 seata概述Seata 中封装了四种分布式事务模式&#xff0c;分别是&#xff1a;AT 模式&#xff0c;TCC 模式&#xff0c;Saga 模式&#xff0c;XA 模式&#xff0c; 今天我们来聊聊seata seata 概述 在微服务架构下&#xff0c;由于数据库和应用服务的拆分&#xff0c…...

为什么设计制造行业需要数据加密?

设计制造行业是一个涉及多种技术、工艺、材料和产品的广泛领域&#xff0c;它对经济和社会的发展有着重要的影响。然而&#xff0c;随着数字化、智能化和网络化的发展&#xff0c;设计制造行业也面临着越来越多的数据安全风险&#xff0c;如数据泄露、数据篡改、数据窃取等。这…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...