el-upload上传图片图片、el-load默认图片重新上传、el-upload初始化图片、el-upload编辑时回显图片

news2024/10/9 18:21:00
  • 问题
    我用el-upload上传图片,再上一篇文章已经解决了,el-upload上传图片给SpringBoot后端,但是又发现了新的问题,果然bug是一个个的冒出来的。新的问题是el-upload编辑时回显图片的保存
    • 问题描述:回显图片需要将默认的 file-list设置为data中的属性,以设置默认值。如下,设置为imgList
 <el-upload
            action=""
            list-type="picture-card"
            multiple
            :on-change="handlChange"
            :file-list="imgList"
            :on-error="handleErr"
            ref="upload"
            :limit="10"
            accept=".jpg,.png,.jpeg"
            :on-exceed="handleMaxNum"

            :auto-upload="false">
            <i slot="default" class="el-icon-plus"></i>
            <div slot="file" slot-scope="{file}">
              <img
                class="el-upload-list__item-thumbnail"
                :src="file.url" alt=""
              >
              <span class="el-upload-list__item-actions">
                <span
                  class="el-upload-list__item-preview"
                  @click="handlePictureCardPreview(file)"
                >
                  <i class="el-icon-zoom-in"></i>
                </span>

                <span

                  class="el-upload-list__item-delete"
                  @click="handleRemove(file)"
                >
                  <i class="el-icon-delete"></i>
                </span>
              </span>
            </div>
          </el-upload>

但是这样的自己设置的值,他的格式是这样的:

this.imgList = this.imgList.map(url => ({
          url: url,
        })

与自己上传文件通过:file_list得到的内容不同,(也就是如果你有个添加图片的功能,有个编辑图片的功能,编辑功能你要设置初始值,但是他们的imgList不一样),有图为证
在这里插入图片描述
在这里插入图片描述
这会导致什么呢?首先,我们需要将imgList的文件转成FormData格式的文件传给后端,通过获取file-ist,可以通过:on-change="handlChange"获取

 handleChange(file, fileList) {
      this.imgList = fileList;
    },
  1. 如果你是添加图片的功能的时候,他是没问题的,可以直接使用
    formData.append('files', item.raw);转成FormData的类型。
  2. 但是如果你是要回显图片再保存,即编辑的功能,这个时候你要设置初始值,即用上面所说的方式设置。这种格式的的imgList,就不能直接使用 formData.append('files', item.raw);这种方式转成FormData,而要使用fetch的方式
  • 解决
    下面是解决的代码,可以先对imgList的url进行判断,因为自己上传的url开头是不带"blob"的,顺便说一下,因为fetch是异步的,所以要通过设置Promise,等fetch全部执行完再进行保存图片,否则FormData还是会为空
this.imgList.forEach(item => {
    let url = item.url;
    if(url.startsWith("blob")){
      formData.append('files', item.raw);
    }
    else {
      let promise = fetch(url, {
          headers: new Headers({
            'Origin': location.origin
          }),
          mode: 'no-cors'
        }
      )
        .then(response => response.blob())
        .then(blob => {
          // 创建 URL 对象以便提取文件名

          let filename = url.split('/').pop();

          // 创建一个虚拟的 File 对象
          let file = new File([blob], filename, {type: 'image/bmp,image/jpeg,image/png,image/webp'});
          console.log(file)
          formData.append('files', file);

        })
        .catch(error => {
          console.error('Failed to fetch image:', error);
        });
      promises.push(promise);
    }
  });
  Promise.all(promises).then(() => {
  console.log("formdata", formData)

         let uri = "/" + newAttractionId
         saveImgs(uri, formData)
           .then(resPic => {
             if (resPic.data.success) {
               // this.$message({
               //   type:"success",
               //   message:resPic.data.msg
               // })
             } else {
               this.$message({
                 type: "info",
                 message: resPic.data.msg
               })
             }

           }).catch(err => {
           console.log("出错", err)
         })

整合主要代码如下

<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
  <el-dialog :title="title" :visible.sync="editFormVisible" width="35%" @click="closeDialog">
     <el-form-item label="图片" prop="imgList">
          <!--          :file-List可以填默认值-->
          <el-upload
            action=""
            list-type="picture-card"
            multiple
            :on-change="handleChange"
            :file-list="imgList"
            :on-error="handleErr"
            ref="upload"
            :limit="10"
            accept=".jpg,.png,.jpeg"
            :on-exceed="handleMaxNum"

            :auto-upload="false">
            <i slot="default" class="el-icon-plus"></i>
            <div slot="file" slot-scope="{file}">
              <img
                class="el-upload-list__item-thumbnail"
                :src="file.url" alt=""
              >
              <span class="el-upload-list__item-actions">
                <span
                  class="el-upload-list__item-preview"
                  @click="handlePictureCardPreview(file)"
                >
                  <i class="el-icon-zoom-in"></i>
                </span>

                <span

                  class="el-upload-list__item-delete"
                  @click="handleRemove(file)"
                >
                  <i class="el-icon-delete"></i>
                </span>
              </span>
            </div>
          </el-upload>
        </el-form-item>
      </el-form>
      
data() {  

      imgList: [],
}
methods: {
handleRemove(file) {

      let arr = this.$refs.upload.uploadFiles
      console.log("arr是",arr)
      // 2.从pics数组中,找到图片对应的索引值
      let index = arr.indexOf(file)
      // 3.调用splice方法,移除图片信息
      arr.splice(index, 1)
      this.imgList=arr
      console.log(this.imgList)

    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    handleChange(file, fileList) {
      this.imgList = fileList;
    },
    handleMaxNum() {
      this.$message({
        type: "info",
        message: "最多选择10张图片"
      })
    },
// 编辑、增加页面保存方法
    subm**加粗样式**itForm(editData) {
      this.loading = true

      this.$refs[editData].validate(valid => {
          if (valid) {
            attractionSave(this.editForm)
              .then(res => {
                  this.editFormVisible = false

                  // console.log(res)
                  if (res.data.success) {

                    let newAttractionId = res.data.attractionId

                    //信息保存成功后,保存图片
                    if ( newAttractionId != '') {
                      let formData = new FormData(); // 用 FormData 存放上传文件

                      // 将图片转为 FormData 格式
                      let promises = [];
                      this.imgList.forEach(item => {
                        let url = item.url;
                        if(url.startsWith("blob")){
                          formData.append('files', item.raw);
                        }
                        else {
                          let promise = fetch(url, {
                              headers: new Headers({
                                'Origin': location.origin
                              }),
                              mode: 'no-cors'
                            }
                          )
                            .then(response => response.blob())
                            .then(blob => {
                              // 创建 URL 对象以便提取文件名

                              let filename = url.split('/').pop();

                              // 创建一个虚拟的 File 对象
                              let file = new File([blob], filename, {type: 'image/bmp,image/jpeg,image/png,image/webp'});
                              console.log(file)
                              formData.append('files', file);

                            })
                            .catch(error => {
                              console.error('Failed to fetch image:', error);
                            });
                          promises.push(promise);
                        }
                      });


                      Promise.all(promises).then(() => {
                        console.log("formdata", formData)

                        let uri = "/" + newAttractionId
                        saveImgs(uri, formData)
                          .then(resPic => {
                            if (resPic.data.success) {
                              // this.$message({
                              //   type:"success",
                              //   message:resPic.data.msg
                              // })
                            } else {
                              this.$message({
                                type: "info",
                                message: resPic.data.msg
                              })
                            }

                          }).catch(err => {
                          console.log("出错", err)
                        })
                      })
                    }


                    this.$message({
                      type: 'success',
                      message: res.data.msg
                    })
                  } else {
                    this.$message({
                      type: 'info',
                      message: res.data.msg
                    })
                  }

                }
              )
              .catch(err => {
                this.editFormVisible = false
                this.loading = false
                this.$message.error('保存失败,请稍后再试!')
                console.log(err)

                return false
              })
            var that = this
            setTimeout(function () {
              that.loading = false;
              that.getData()
            }, 1000)

          } else {
            this.loading = false
            return false
          }
        }
      )

    },
     //显示编辑界面
    handleEdit: function (index, row) {

      this.editFormVisible = true
      if (row != undefined && row != 'undefined') {
        this.title = '修改';
        this.imgList=row.imgList
        this.imgList = this.imgList.map(url => ({
          url: url,
        }));
        console.log("list", this.imgList)

      } 
    }
  </el-dialog>

同时,附上SpringBoot业务层代码

  @Override
    public ResJson savePicture(List<MultipartFile> files, String attractionLocationById) {
        ResJson resJson = new ResJson();
        // 获取文件夹中所有文件的列表
        File file1 = new File(attractionLocationById);
        File[] folderFiles = file1.listFiles();

         // 创建一个 HashSet,用于存储上传文件的名称
        Set<String> uploadedFileNames = new HashSet<>();
        if(files==null) {
            for (File folderFile : folderFiles) {
                if (folderFile.delete()) {

                    System.out.println("删除文件: " + folderFile.getName() + " 成功");
                } else {
                    System.out.println("删除文件: " + folderFile.getName() + " 失败");
                }
            }
            file1.delete();
            return null;
        }
        for (MultipartFile file : files) {
            uploadedFileNames.add(file.getOriginalFilename());
        }

        System.out.println("uploadedFileNames = " + uploadedFileNames);


        //删除图片,其实只要全部删除,再重新下载即可,考虑到图片数量可能多,就搞成判断了
        if(folderFiles!=null) {
            // 遍历文件夹中的文件
            for (File folderFile : folderFiles) {
                String folderFileName = folderFile.getName();
                // 如果文件夹中的文件不在上传的文件列表中,则删除该文件

                if (!uploadedFileNames.contains(folderFileName)) {
                    System.out.println(folderFileName);
                    if (folderFile.delete()) {

                        System.out.println("删除文件: " + folderFile.getName() + " 成功");
                    } else {
                        System.out.println("删除文件: " + folderFile.getName() + " 失败");
                    }
                }
                else{
                    uploadedFileNames.remove(folderFileName);
                }

            }
        }


        // 保存上传的文件
        for (MultipartFile file : files) {
            try {

                String originalFilename = file.getOriginalFilename();
                //如果已经有了,在上面的被移除了,只有在剩下的没被排除内的就下载
                if(uploadedFileNames.contains(originalFilename)) {
                    // 构建真实的文件路径
                    Path path = Paths.get(attractionLocationById + originalFilename);

                    // 确保目录路径存在
                    Files.createDirectories(path.getParent());
                    // 将上传文件保存到指定位置
                    file.transferTo(path);
                    System.out.println("图片保存成功");
                    System.out.println("保存+1");
                }
                resJson.setMsg("图片保存成功");
                resJson.setSuccess(true);
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("上传失败");
                resJson.setMsg("图片保存失败");
                resJson.setSuccess(false);
            }

        }

        return resJson;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1568329.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

A53 cache的架构解读

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; 引流关键词:缓存,高速缓存,cache, CCI,CMN,CCI-550,CCI-500,DSU,SCU,L1,L2,L3,system cache, Non-cacheable,Cacheable, non-shareable,inner-shareable,outer-shareable, optee、…

精准扶贫管理系统|基于Springboot的精准扶贫管理系统设计与实现(源码+数据库+文档)

精准扶贫管理系统目录 目录 基于Springboot的精准扶贫管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 &#xff08;1&#xff09;用户信息管理 &#xff08;2&#xff09;贫困户信息管理 &#xff08;3&#xff09;新闻类型管理 &a…

【Java EE】关于Maven

文章目录 &#x1f38d;什么是Maven&#x1f334;为什么要学Maven&#x1f332;创建⼀个Maven项目&#x1f333;Maven核心功能&#x1f338;项目构建&#x1f338;依赖管理 &#x1f340;Maven Help插件&#x1f384;Maven 仓库&#x1f338;本地仓库&#x1f338;私服 ⭕总结 …

Unity类银河恶魔城学习记录12-3 p125 Limit Inventory Slots源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Inventory.cs using Newtonsoft.Json.Linq; using System.Collections; us…

Linux 线程:线程互斥、互斥量、可重入与线程安全

目录 一、线程互斥 1、回顾相关概念 2、抢票场景分析代码 多个线程同时操作全局变量 产生原因 如何解决 二、互斥量 1、概念 2、初始化互斥量&#xff1a; 方法1&#xff1a;静态分配 方法2&#xff1a;动态分配 3、销毁互斥量&#xff1a; 4、加锁和解锁 示例抢…

多忽悠几次AI全招了!Anthropic警告:长上下文成越狱突破口,GPT羊驼Claude无一幸免

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 大模型厂商在上下文长度上卷的不可开交之际&#xff0c;一项最新研究泼来了一盆冷水—— Cl…

计算机网络-HTTP相关知识-HTTP的发展

HTTP/1.1 特点&#xff1a; 简单&#xff1a;HTTP/1.1的报文格式包括头部和主体&#xff0c;头部信息是键值对的形式&#xff0c;使得其易于理解和使用。灵活和易于扩展&#xff1a;HTTP/1.1的请求方法、URL、状态码、头字段等都可以自定义和扩展&#xff0c;使得其具有很高的…

Golang 内存管理和垃圾回收底层原理(一)

一、这篇文章我们来聊聊Golang内存管理和垃圾回收&#xff0c;主要注重基本底层原理讲解&#xff0c;进一步实战待后续文章 1、这篇我们来讨论一下Golang的内存管理 先上结构图 从图我们来讲Golang的基本内存结构&#xff0c;内存结构可以分为&#xff1a;协程缓存、中央缓存…

Redis的高可用(主从复制、哨兵模式、集群)的概述及部署

目录 一、Redis主从复制 1、Redis的主从复制的概念 2、Redis主从复制的作用 ①数据冗余&#xff1a; ②故障恢复&#xff1a; ③负载均衡&#xff1a; ④高可用基石&#xff1a; 3、Redis主从复制的流程 4、Redis主从复制的搭建 4.1、配置环境以及安装包 4.2所有主机…

chabot项目介绍

项目介绍 整体的目录如下所示&#xff1a; 上述的项目结构中出了model是必须的外&#xff0c;其他的都可以根据训练的代码参数传入进行调整&#xff0c;有些不需要一定存在data train.pkl:对原始训练语料进行tokenize之后的文件,存储一个list对象&#xff0c;list的每条数据表…

解密AI人工智能的整体分层架构:探索智能科技的未来之路

随着人工智能技术的迅猛发展&#xff0c;AI已经渗透到我们生活的方方面面。而支撑AI人工智能系统运作的核心是其整体分层架构。本文将深入探讨AI人工智能的整体分层架构&#xff0c;揭示其中的奥秘&#xff0c;探索智能科技的未来之路。 ### AI人工智能整体分层架构的重要性 …

Linux上安装DM8(达梦数据库),SpringBoot集成达梦

1.达梦数据库在Linux上的安装 官方手册:https://eco.dameng.com/document/dm/zh-cn/start/install-dm-linux-prepare.html 1.1下载安装包 官网:https://www.dameng.com/list_103.html 点击”服务与合作”--> “下载中心” 这里选择对应的cpu和操作系统(举个例子:windows版本…

Java基础 - 代码练习

第一题&#xff1a;集合的运用&#xff08;幸存者&#xff09; public class demo1 {public static void main(String[] args) {ArrayList<Integer> array new ArrayList<>(); //一百个囚犯存放在array集合中Random r new Random();for (int i 0; i < 100; …

JimuReport 积木报表

一款免费的数据可视化报表&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于 excel 操作风格&#xff0c;通过拖拽完成报表设计…

从零到百万富翁:ChatGPT + Pinterest

原文&#xff1a;Zero to Millionaire Online: ChatGPT Pinterest 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 在社交媒体上赚取百万美元 - 逐步指南&#xff0c;如何在线赚钱版权 献给&#xff1a; 我将这本书&#xff0c;“从零到百万富翁在线&#xff1a;Chat…

【御控物联】JavaScript JSON结构转换(18):数组To对象——多层属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、案例之《JSON数组 To JSON对象》三、代码实现四、在线转换工具五、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0c;生成新的JS…

基于PHP的校园招聘管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的校园招聘管理系统 一 介绍 此校园招聘管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为个人用户&#xff0c;企业和管理员三种。 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二…

JS——判断节假日(假日包括周末,不包括调休上班的周末)

思路&#xff1a;创建两个数组&#xff0c;数组1为节假日数组&#xff0c;数组2为是周末上班日期数组。如果当前日期&#xff08;或某日期&#xff09;同时满足2个条件&#xff08;1.在节假日数组内或在周末。2.不在周末上班日期数组&#xff09;即为节假日&#xff0c;否则即为…

Mybatis-Plus05(分页插件)

分页插件 MyBatis Plus自带分页插件&#xff0c;只要简单的配置即可实现分页功能 1. 添加配置类 Configuration MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处 public class MybatisPlusConfig {Bean public MybatisPlusIntercepto…

LeetCode-105. 从前序与中序遍历序列构造二叉树【树 数组 哈希表 分治 二叉树】

LeetCode-105. 从前序与中序遍历序列构造二叉树【树 数组 哈希表 分治 二叉树】 题目描述&#xff1a;解题思路一&#xff1a;暴力搜索解题思路二&#xff1a;哈希查找解题思路三&#xff1a; 题目描述&#xff1a; 给定两个整数数组 preorder 和 inorder &#xff0c;其中 pr…