前端使用 Element Plus架构vue3.0实现图片拖拉拽,后等比压缩,上传到Spring Boot后端

news2024/12/27 14:11:00

图片拖拉拽 等比压缩上传

为了在前端对图片文件进行等比压缩后再上传到后端,可以使用 canvas 元素来实现图片的压缩。以下是一个详细的实现步骤:

  1. 前端实现图片等比压缩:使用 canvas 元素对图片进行压缩。
  2. 前端上传压缩后的图片:使用 el-upload 组件上传压缩后的图片。
  3. 后端接收并保存图片:在 Spring Boot 中接收上传的图片并保存。

下面是一个详细的实现示例。

1. 前端实现图片等比压缩

首先,确保你已经安装了 jszip 和 file-saver 库来处理文件压缩。

bash

npm install jszip file-saver

2. 创建拖拽上传组件

修改 DragUpload.vue 组件以支持图片等比压缩和上传。

vue

<template>
  <div>
    <el-upload
      class="upload-dragger"
      drag
      action="http://localhost:8080/upload"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :file-list="fileList"
      :on-change="handleChange"
      :auto-upload="false"
      multiple>
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <template #tip>
        <div class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
      </template>
    </el-upload>
    <el-button style="margin-top: 20px;" type="success" @click="submitUpload">上传到服务器</el-button>
    <div v-if="fileList.length > 0">
      <h3>已上传文件列表:</h3>
      <ul>
        <li v-for="(file, index) in fileList" :key="index">
          {{ file.name }}
          <img v-if="isImage(file)" :src="file.url" alt="Uploaded file" style="max-width: 100px; margin-left: 10px;" />
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';

export default {
  setup() {
    const fileList = ref([]);

    const handleRemove = (file, fileList) => {
      console.log(file, fileList);
    };

    const handlePreview = (file) => {
      console.log(file);
    };

    const handleChange = (file, fileList) => {
      fileList = fileList.slice(-3); // 限制最多上传3个文件
      fileList.forEach((file) => {
        if (file.raw) {
          file.url = URL.createObjectURL(file.raw);
        }
      });
      fileList.value = fileList;
    };

    const submitUpload = async () => {
      const zip = new JSZip();
      for (const file of fileList.value) {
        if (isImage(file)) {
          const compressedFile = await compressImage(file.raw);
          zip.file(file.name, compressedFile);
        } else {
          zip.file(file.name, file.raw);
        }
      }

      const content = await zip.generateAsync({ type: 'blob' });
      const formData = new FormData();
      formData.append('file', content, 'files.zip');

      const response = await fetch('http://localhost:8080/upload', {
        method: 'POST',
        body: formData
      });

      if (response.ok) {
        console.log('文件上传成功');
      } else {
        console.error('文件上传失败');
      }
    };

    const isImage = (file) => {
      const imageTypes = ['image/jpeg', 'image/png'];
      return imageTypes.includes(file.raw.type);
    };

    const compressImage = (file) => {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (event) => {
          const img = new Image();
          img.onload = () => {
            const canvas = document.createElement('canvas');
            const MAX_WIDTH = 800; // 设置最大宽度
            const MAX_HEIGHT = 800; // 设置最大高度
            let width = img.width;
            let height = img.height;

            if (width > height) {
              if (width > MAX_WIDTH) {
                height *= MAX_WIDTH / width;
                width = MAX_WIDTH;
              }
            } else {
              if (height > MAX_HEIGHT) {
                width *= MAX_HEIGHT / height;
                height = MAX_HEIGHT;
              }
            }

            canvas.width = width;
            canvas.height = height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0, width, height);

            canvas.toBlob((blob) => {
              resolve(blob);
            }, file.type, 0.8); // 0.8 是压缩质量
          };
          img.onerror = reject;
          img.src = event.target.result;
        };
        reader.onerror = reject;
        reader.readAsDataURL(file);
      });
    };

    return {
      fileList,
      handleRemove,
      handlePreview,
      handleChange,
      submitUpload,
      isImage
    };
  }
};
</script>

<style scoped>
.upload-dragger {
  width: 600px;
  margin: 0 auto;
}
</style>

3. 后端 Spring Boot 接收并解压文件

创建一个 Spring Boot 项目来接收并解压上传的文件。

3.1 添加依赖

在 pom.xml 中添加必要的依赖:

xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-compress</artifactId>
        <version>1.21</version>
    </dependency>
</dependencies>
3.2 创建文件上传控制器

创建一个控制器来处理文件上传和解压。

java

package com.example.demo.controller;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;

@RestController
public class FileUploadController {

    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            // 创建临时文件存储上传的压缩文件
            File tempFile = File.createTempFile("uploaded", ".zip");
            file.transferTo(tempFile);

            // 解压文件
            ZipFile zipFile = new ZipFile(tempFile);
            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();

            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();
                if (!entry.isDirectory()) {
                    File entryFile = new File("uploads/" + entry.getName());
                    entryFile.getParentFile().mkdirs();
                    try (InputStream inputStream = zipFile.getInputStream(entry);
                         FileOutputStream outputStream = new FileOutputStream(entryFile)) {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = inputStream.read(buffer)) > 0) {
                            outputStream.write(buffer, 0, length);
                        }
                    }
                }
            }

            // 删除临时文件
            tempFile.delete();

            return "文件上传并解压成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "文件上传或解压失败";
        }
    }
}
3.3 配置文件上传大小限制

在 application.properties 中配置文件上传大小限制:

properties

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
3.4 创建上传目录

确保项目中有一个 uploads 目录来存储解压后的文件。你可以在项目根目录下创建这个目录,或者在代码中动态创建。

4. 运行项目

  1. 启动 Spring Boot 项目

    bash

mvn spring-boot:run

     2.启动 Vue 项目

        bash

npm run serve

5. 测试上传功能

  1. 打开浏览器,访问 Vue 项目(通常是 http://localhost:8080)。
  2. 使用拖拽上传组件上传图片文件。
  3. 点击“上传到服务器”按钮,图片将被等比压缩并上传到 Spring Boot 后端。
  4. 后端接收文件并解压到 uploads 目录中。

通过以上步骤,你可以在前端实现图片等比压缩并在后端 Spring Boot 架构中接收文件。

文件的拖拉拽上传

在前端实现文件压缩并在后端 Spring Boot 架构中接收文件,可以分为以下几个步骤:

  1. 前端实现文件压缩:使用 JavaScript 库(如 jszip)来压缩文件。
  2. 前端上传压缩后的文件:使用 el-upload 组件上传压缩后的文件。
  3. 后端接收并解压文件:在 Spring Boot 中接收上传的压缩文件并解压。

下面是一个详细的实现示例。

1. 前端实现文件压缩

首先,安装 jszip 和 file-saver 库来处理文件压缩和保存。

bash

npm install jszip file-saver

2. 创建拖拽上传组件

修改 DragUpload.vue 组件以支持文件压缩和上传。

vue

<template>
  <div>
    <el-upload
      class="upload-dragger"
      drag
      action="http://localhost:8080/upload"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :file-list="fileList"
      :on-change="handleChange"
      :auto-upload="false"
      multiple>
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <template #tip>
        <div class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
      </template>
    </el-upload>
    <el-button style="margin-top: 20px;" type="success" @click="submitUpload">上传到服务器</el-button>
    <div v-if="fileList.length > 0">
      <h3>已上传文件列表:</h3>
      <ul>
        <li v-for="(file, index) in fileList" :key="index">
          {{ file.name }}
          <img v-if="isImage(file)" :src="file.url" alt="Uploaded file" style="max-width: 100px; margin-left: 10px;" />
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';

export default {
  setup() {
    const fileList = ref([]);

    const handleRemove = (file, fileList) => {
      console.log(file, fileList);
    };

    const handlePreview = (file) => {
      console.log(file);
    };

    const handleChange = (file, fileList) => {
      fileList = fileList.slice(-3); // 限制最多上传3个文件
      fileList.forEach((file) => {
        if (file.raw) {
          file.url = URL.createObjectURL(file.raw);
        }
      });
      fileList.value = fileList;
    };

    const submitUpload = async () => {
      const zip = new JSZip();
      fileList.value.forEach((file) => {
        zip.file(file.name, file.raw);
      });

      const content = await zip.generateAsync({ type: 'blob' });
      const formData = new FormData();
      formData.append('file', content, 'files.zip');

      const response = await fetch('http://localhost:8080/upload', {
        method: 'POST',
        body: formData
      });

      if (response.ok) {
        console.log('文件上传成功');
      } else {
        console.error('文件上传失败');
      }
    };

    const isImage = (file) => {
      const imageTypes = ['image/jpeg', 'image/png'];
      return imageTypes.includes(file.raw.type);
    };

    return {
      fileList,
      handleRemove,
      handlePreview,
      handleChange,
      submitUpload,
      isImage
    };
  }
};
</script>

<style scoped>
.upload-dragger {
  width: 600px;
  margin: 0 auto;
}
</style>

3. 后端 Spring Boot 接收并解压文件

创建一个 Spring Boot 项目来接收并解压上传的文件。

3.1 添加依赖

在 pom.xml 中添加必要的依赖:

xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-compress</artifactId>
        <version>1.21</version>
    </dependency>
</dependencies>
3.2 创建文件上传控制器

创建一个控制器来处理文件上传和解压。

java

package com.example.demo.controller;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;

@RestController
public class FileUploadController {

    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            // 创建临时文件存储上传的压缩文件
            File tempFile = File.createTempFile("uploaded", ".zip");
            file.transferTo(tempFile);

            // 解压文件
            ZipFile zipFile = new ZipFile(tempFile);
            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();

            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();
                if (!entry.isDirectory()) {
                    File entryFile = new File("uploads/" + entry.getName());
                    entryFile.getParentFile().mkdirs();
                    try (InputStream inputStream = zipFile.getInputStream(entry);
                         FileOutputStream outputStream = new FileOutputStream(entryFile)) {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = inputStream.read(buffer)) > 0) {
                            outputStream.write(buffer, 0, length);
                        }
                    }
                }
            }

            // 删除临时文件
            tempFile.delete();

            return "文件上传并解压成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "文件上传或解压失败";
        }
    }
}
3.3 配置文件上传大小限制

在 application.properties 中配置文件上传大小限制:

properties

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
3.4 创建上传目录

确保项目中有一个 uploads 目录来存储解压后的文件。你可以在项目根目录下创建这个目录,或者在代码中动态创建。

4. 运行项目

  1. 启动 Spring Boot 项目

    bash

mvn spring-boot:run

2.启动 Vue 项目

bash

npm run serve

5. 测试上传功能

  1. 打开浏览器,访问 Vue 项目(通常是 http://localhost:8080)。
  2. 使用拖拽上传组件上传文件或图片。
  3. 点击“上传到服务器”按钮,文件将被压缩并上传到 Spring Boot 后端。
  4. 后端接收文件并解压到 uploads 目录中。

通过以上步骤,你可以在前端实现文件压缩并在后端 Spring Boot 架构中接收文件。

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

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

相关文章

深入浅出 MyBatis | CRUD 操作、配置解析

3、CRUD 3.1 namespace namespace 中的包名要和 Dao/Mapper 接口的包名一致&#xff01; 比如将 UserDao 改名为 UserMapper 运行发现抱错&#xff0c;这是因为 UserMapper.xml 中没有同步更改 namespace 成功运行 给出 UserMapper 中的所有接口&#xff0c;接下来一一对…

基于c语言的union、字符串、格式化输入输出

结构体之共用体union 共用体也叫联合体&#xff0c;其关键词为union 与结构体不同的是&#xff0c;共用体所开辟的存储空间仅仅为其中最长类型变量的存储空间而不是全部变量的存储空间&#xff0c;由于同一内存单元在同一时间内只能存放其中一种的数据类型&#xff0c;因此在每…

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…

AI开发:使用支持向量机(SVM)进行文本情感分析训练 - Python

支持向量机是AI开发中最常见的一种算法。之前我们已经一起初步了解了它的概念和应用&#xff0c;今天我们用它来进行一次文本情感分析训练。 一、概念温习 支持向量机&#xff08;SVM&#xff09;是一种监督学习算法&#xff0c;广泛用于分类和回归问题。 它的核心思想是通过…

Linux-----进程处理(子进程创建)

【尚硅谷嵌入式Linux应用层开发&#xff0c;linux网络编程&#xff0c;linux进程线程&#xff0c;linux文件io】https://www.bilibili.com/video/BV1DJ4m1M77z?p35&vd_source342079de7c07f82982956aad8662b467 main函数 fork创建进程 fork()参数 /*** brief 创建一个子进…

一种寻路的应用

应用背景 利用长途车进行货物转运的寻路计算。例如从深圳到大连。可以走有很多条长途车的路线。需要根据需求计算出最合适路线。不同的路线的总里程数、总价、需要的时间不一样。客户根据需求进行选择。主要有一些细节&#xff1a; 全国的长途车车站的数据的更新&#xff1a; …

2. FPGA基础了解--全局网络

前言 引入扇出的概念介绍FPGA中的全局网络为后续时序优化埋下伏笔 扇出 在FPGA设计中扇出是一个重要的概念&#xff0c;所谓的扇出就是一个控制信号所能控制的数据信号的总个数&#xff0c;比如ctrl信号的扇出就是16 reg ctrl 0; reg [15:0] out 0; always (posedge c…

Excel中一次查询返回多列

使用Excel或wps的时候&#xff0c;有时候需要一次查询返回多列内容&#xff0c;这种情况可以选择多次vlookup或者多次xlookup&#xff0c;但是这种做法费时费力不说&#xff0c;效率还有些低下&#xff0c;特别是要查询的列数过多时。我放了3种查询方法&#xff0c;效果图&…

智能化军事【五】精确制导武器智能化实现

文章目录 前言精确制导武器智能化实现基于深度学习实现的智能化功能基于强化学习实现的智能化功能强化学习深度强化学习 网络模型轻量化网络剪枝&#xff08;通道剪枝&#xff09;技术层剪枝权值量化技术低秩近似技术知识蒸馏技术强化学习联合训练 解决有效训练样本不足或获取困…

解锁高效密码:适当休息,让学习状态满格

一、“肝帝” 的困境 在当今竞争激烈的职场中&#xff0c;“肝帝” 现象屡见不鲜。超长工时仿佛成为了许多行业的 “标配”&#xff0c;从互联网企业的 “996”“007”&#xff0c;到传统制造业的轮班倒、无休无止的加班&#xff0c;员工们的工作时间被不断拉长。清晨&#xff…

asp.net 高校学生勤工俭学系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm 等开发框架&#xff09; vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…

WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

RTMW:实时多人2D和3D 全人体姿态估计

单位&#xff1a;上海AI实验室 代码&#xff1a;mmpose/tree/main/projects/rtmpose 系列文章目录 RTMO: 面向高性能单阶段的实时多人姿态估计 目录 系列文章目录摘要一、背景二、相关工作2.1 自上而下的方法。2.2 坐标分类。2.3 3D Pose 3 实验方法3.1.1 任务限制3.1.3训练技…

AI智能养站神器-SEO助理原创文章批量生成发布工具

很多站长最头疼的就是网站每天的内容更新&#xff0c;因为不知道写什么&#xff0c;采集被人的文章又会被定义为抄袭&#xff0c;而且现在伪原创已经没有多大的效果了&#xff0c;所以今天给大家分享的就是一款AI智能养战神器-SEO助理原创文章批量生成发布工具。 这款工具支持…

用Python开启人工智能之旅(三)常用的机器学习算法与实现

第三部分&#xff1a;常用的机器学习算法与实现 用Python开启人工智能之旅&#xff08;一&#xff09;Python简介与安装 用Python开启人工智能之旅&#xff08;二&#xff09;Python基础 用Python开启人工智能之旅&#xff08;三&#xff09;常用的机器学习算法与实现 用Pyt…

FD(File Descriptor)泄漏

File Descriptor是Linux下概念&#xff0c;fd 是 int类型非负数&#xff01; 进程打开File&#xff0c;Socket&#xff0c;Pipe后生成一个File Descriptor&#xff0c;它是打开这个系统资源的标识符。 Linux每个进程fd最大1024个&#xff0c;超过之后进程 crash&#xff0c;c…

英语单词拼读小程序开发制作介绍

英语单词拼读小程序开发制作介绍本英语单词拼读小程序系统开发的主要功能有&#xff1a; 1、按年级分类展示每个年级阶段的英语单词信息。 2、点击选择的单词进入单词拼读页面&#xff0c;展示英语单词的拼读音标、中文意思、单词发音、拆分词汇发音、用户通过朗读发音对比。通…

TCP客户端模拟链接websocket服务端发送消息(二)

兄弟们&#xff0c;我来填坑了&#xff0c;o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o&#xff0c;前几天写了个tcp模拟websocket客户端的以为完成&#xff0c;后面需要发送消息给服务端&#xff0c;以为简单不就是一个发送消息么&#xff0c;这不是一…

Docker 镜像加速访问方案

在数字化时代&#xff0c;Docker以其轻量级和便捷性成为开发者和运维人员的首选容器技术。然而自2023年5月中旬起&#xff0c;Docker Hub 的访问速度较慢或不稳定&#xff0c;这对依赖Docker Hub拉取镜像的用户来说无疑是一个挑战。本文将提供 Docker Hub 访问的一系列替代方案…

牛客网刷题 ——C语言初阶——BC112小乐乐求和

1.牛客网刷题 ——C语言初阶 牛客网&#xff1a;BC112小乐乐求和 小乐乐最近接触了求和符号Σ&#xff0c;他想计算的结果。但是小乐乐很笨&#xff0c;请你帮助他解答。 输入描述: 输入一个正整数n (1 ≤ n ≤ 109) 输出描述: 输出一个值&#xff0c;为求和结果。 示例1 输…