【前后端的那些事】文件上传组件封装

文章目录

  • 效果
  • 前端代码
  • 后端代码
  • 组件封装

效果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

前端代码

/views/file/file.vue

<template><el-row><el-uploadv-model:file-list="fileList"class="upload-demo"multiple:auto-upload="false":on-preview="handlePreview":on-remove="handleRemove"span="10"style="margin-right: 20px"><el-button type="primary">选择上传的文件</el-button></el-upload><el-button type="success" @click="submit">上传文件</el-button></el-row>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { uploadBatch } from "/src/api/file.ts";import type { UploadProps, UploadUserFile } from "element-plus";const fileList = ref<UploadUserFile[]>([]);const handleRemove: UploadProps["onRemove"] = (file, uploadFiles) => {console.log(file, uploadFiles);
};const handlePreview: UploadProps["onPreview"] = uploadFile => {console.log(uploadFile);
};const submit = () => {console.log(fileList.value);// 封装formDataconst data = new FormData();fileList.value.forEach(element => {data.append("fileList", element.raw);});uploadBatch(data).then(res => {console.log(res);if (res.code === 0) {ElMessage.success("上传成功");} else {ElMessage.error("上传失败: " + res.msg);}});
};
</script>

/src/api/file.ts

import { http } from "@/utils/http";
import { R, baseUrlApi } from "./utils";/** upload batch */
export const uploadBatch = (data: FormData) => {return http.request<R<any>>("post", baseUrlApi("common/file/uploadList"), {data,headers: {"Content-Type": "multipart/form-data"}});
};/** upload */
export const upload = (data: FormData) => {return http.request<R<any>>("post", baseUrlApi("common/file/upload"), {data,headers: {"Content-Type": "multipart/form-data"}});
};

/src/api/utils.ts

export const baseUrlApi = (url: string) => `/api_demo/${url}`;/** 后端返回通用数据类型 */
export type R<T> = {code: Number;msg: String;data: T;
};/** 同步休眠函数, 参数为毫秒 */
export const sleep = (ms: number): Promise<void> => {return new Promise(resolve => setTimeout(resolve, ms));
};/** 分页数据类型 */
export type PageUtils<T> = {/** 总记录数 */totalCount: number;/** 每页记录数 */pageSize: number;/** 总页数 */totalPage: number;/** 当前页数 */currPage: number;/** 列表数据 */list: Array<T>;
};export const getStoreUser = () => {const res = sessionStorage.getItem("user-info");// const res = sessionStorage.getItem("user-info");console.log(res);return JSON.parse(res);
};

后端代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fgbg</groupId><artifactId>webrtc</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.5</version><relativePath/></parent><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><mybatisplus.version>3.3.1</mybatisplus.version><mysql.version>8.0.28</mysql.version><mssql.version>4.0</mssql.version><oracle.version>11.2.0.3</oracle.version><druid.version>1.1.13</druid.version><quartz.version>2.3.0</quartz.version><commons.lang.version>2.6</commons.lang.version><commons.fileupload.version>1.2.2</commons.fileupload.version><commons.io.version>2.5</commons.io.version><commons.codec.version>1.10</commons.codec.version><commons.configuration.version>1.10</commons.configuration.version><shiro.version>1.9.0</shiro.version><jwt.version>0.7.0</jwt.version><kaptcha.version>0.0.9</kaptcha.version><qiniu.version>7.2.23</qiniu.version><aliyun.oss.version>2.8.3</aliyun.oss.version><qcloud.cos.version>4.4</qcloud.cos.version><swagger.version>2.7.0</swagger.version><joda.time.version>2.9.9</joda.time.version><gson.version>2.8.5</gson.version><hutool.version>4.1.1</hutool.version><lombok.version>1.18.4</lombok.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- https://mvnrepository.com/artifact/commons-io/commons-io --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>${commons.lang.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

FileController.java

import com.fgbg.common.R;
import com.fgbg.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;@RestController
@RequestMapping("/common/file")
public class FileController {@Autowired@Qualifier("localFileService")private FileService fileService;/*** 批量文件上传接口*/@RequestMapping("/uploadList")public R uploadBatch(@RequestParam("fileList") List<MultipartFile> fileList) throws IOException {ArrayList<String> ans = new ArrayList<>();for (MultipartFile file : fileList) {String url = fileService.uploadFile(file, UUID.randomUUID().toString().substring(0, 10)+ "-" + file.getOriginalFilename());ans.add(url);}return R.ok().put("data", ans);}/*** 上传文件接口*/@RequestMapping("/upload")public R upload(@RequestParam("file") MultipartFile file) throws IOException {String url = fileService.uploadFile(file, UUID.randomUUID().toString().substring(0, 10)+ "-" + file.getOriginalFilename());return R.ok().put("data", url);}/*** 下载接口*/@RequestMapping("/download/{fileName}")public void download(@PathVariable("fileName") String fileName, HttpServletRequest request, HttpServletResponse response) {fileService.downloadFile(fileName, request, response);}/*** 删除接口*/@RequestMapping("/delete")public R deleteFile(@RequestParam String fileName) {boolean flag = fileService.deleteFile(fileName);return R.ok().put("data", flag);}
}

FileService.java

import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public interface FileService {/*** 上传图片, 返回url*/String uploadFile(MultipartFile file, String fileName) throws IOException;/*** 下载图片*/void downloadFile(String fileName, HttpServletRequest request, HttpServletResponse response);/*** 删除图片*/boolean deleteFile(String fileName);
}

LocalFileServiceImpl.java

import com.fgbg.service.FileService;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;/*** 基于本地的文件管理服务*/
@Service("localFileService")
public class LocalFileServiceImpl implements FileService {/*** 文件访问域名(请求下载的接口)*/private static final String DOMAIN = "http://localhost:9006/api_demo/common/file/download/";/*** 文件物理存储位置*/private static final String STORE_DIR = "D:\\java_code\\webrtc\\src\\main\\resources\\file";/*** 上传图片, 返回url** @param file* @param fileName*/@Overridepublic String uploadFile(MultipartFile file, String fileName) throws IOException {// 获取文件流InputStream is = file.getInputStream();// 在服务器中存储文件FileUtils.copyInputStreamToFile(is, new File(STORE_DIR + fileName));// 返回文件urlString url = DOMAIN + fileName;System.out.println("文件url: " + url);return url;}/*** 下载图片** @param fileName*/@Overridepublic void downloadFile(String fileName, HttpServletRequest request, HttpServletResponse response) {// 获取真实的文件路径String filePath = STORE_DIR + fileName;System.out.println("++++完整路径为:"+filePath);try {// 下载文件// 设置响应头response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);// 读取文件内容并写入输出流Files.copy(Paths.get(filePath), response.getOutputStream());response.getOutputStream().flush();} catch (IOException e) {response.setStatus(404);}}/*** 删除图片** @param fileName*/@Overridepublic boolean deleteFile(String fileName) {// 获取真实的文件路径String filePath = STORE_DIR + fileName;System.out.println("++++完整路径为:"+filePath);File file = new File(filePath);return file.delete();}
}

组件封装

fileUpload.vue组件封装

<template><el-row><el-uploadv-model:file-list="localFileList"class="upload-demo"multiple:auto-upload="false":on-preview="handlePreview":on-remove="handleRemove"span="10"style="margin-right: 20px"><el-button type="primary">选择上传的文件</el-button></el-upload></el-row>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import type { UploadProps, UploadUserFile } from "element-plus";// 定义数据
const props = defineProps({fileList: {type: Array<UploadUserFile>,default: () => []}
});// 将父组件的数据拆解为子组件数据
const localFileList = ref(props.fileList);// 监听localFileList, 跟新父组件数据
watch(localFileList,newValue => {emits("update:fileList", newValue);},{deep: true}
);// 定义组件事件, 跟新fileList
const emits = defineEmits(["update:fileList"]);const handleRemove: UploadProps["onRemove"] = (file, uploadFiles) => {console.log(file, uploadFiles);
};const handlePreview: UploadProps["onPreview"] = uploadFile => {console.log(uploadFile);
};
</script>

组件调用

<script setup lang="ts">
import FileUpload from "./fileUpload.vue";
import { ref } from "vue";
import type { UploadUserFile } from "element-plus";
import { ElMessage } from "element-plus";
import { uploadBatch } from "/src/api/file.ts";const fileList = ref<Array<UploadUserFile>>();const submit = () => {console.log(fileList.value);// 封装formDataconst data = new FormData();fileList.value.forEach(element => {data.append("fileList", element.raw);});uploadBatch(data).then(res => {console.log(res);if (res.code === 0) {ElMessage.success("上传成功");} else {ElMessage.error("上传失败: " + res.msg);}});
};
</script><template><el-row><FileUpload v-model:fileList="fileList" /><el-button type="success" @click="submit">上传文件</el-button></el-row>
</template><style lang="scss" scoped></style>

封装组件使用的效果
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Swiper.js:不识这个轮播图js库,说明你的前端还未入门

hello&#xff0c;我是贝格前端工场&#xff0c;本期给大家带来轮播图的s库&#xff1a;Swiper.js&#xff0c;用这个类库处理轮播图、幻灯片、画廊那是得心应手&#xff0c;非常的easy&#xff0c;欢迎老铁们点赞关注&#xff0c;如有前端定制开发需求可以私信我们。 一、Swip…

网络编程、UDP、TCP

计算机网络 就是将地理位置不同的具有独立功能的多台计算及外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统、网络管理软件以及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统 目的 传播交流信息、数据交换、通信 如何做…

TensorRT及CUDA自学笔记003 CUDA编程模型、CUDA线程模型及其管理、CUDA内存模型及其管理

TensorRT及CUDA自学笔记003 CUDA编程模型、CUDA线程模型及其管理、CUDA内存模型及其管理 各位大佬&#xff0c;这是我的自学笔记&#xff0c;如有错误请指正&#xff0c;也欢迎在评论区学习交流&#xff0c;谢谢&#xff01; CUDA编程模型 我们使用CUDA_C语言进行CUDA编程&am…

【Vue3】‘vite‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

问题 今天拿到别人项目的时候&#xff0c;我平时比较习惯用pnpm&#xff0c;我就使用pnpm i先下载依赖包&#xff0c;下载完成后&#xff0c;启动项目&#xff0c;就开始报以下错误&#xff01; 但是当我执行pnpm i的时候&#xff0c;vite不应该就已经被我下载下来了吗 研究了…

【Java程序设计】【C00307】基于Springboot的基Hadoop的物品租赁管理系统(有论文)

基于Springboot的基Hadoop的物品租赁管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的基于 Hadoop的物品租赁系统的设计与实现&#xff0c;本系统有管理员、用户二种角色权限&#xff1b; 前台首页&#…

day11-项目集成SpringSecurity-今日指数

项目集成SpringSecurity 学习目标 理解自定义认证和授权过滤器流程&#xff1b;理解项目集成SprignSecurity流程&#xff1b; 第一章 自定义认证授权过滤器 1、SpringSecurity内置认证流程 通过研究SpringSecurity内置基于form表单认证的UsernamePasswordAuthenticationFi…

【工程院院士加盟】第四届计算机通信与人工智能国际会议

CCAI 2024 | Xian, Chinahttp://ccai.net/ - IEEE出版&#xff0c;EI核心和Scopus检索 - 工程院院士&#xff0c;IEEE Fellow等学术大咖主题演讲 - 会议时间-地点&#xff1a;2024年5月24-26日&#xff0c;中国西安 会议简介 Brief Introduction 作为人工智能的重要传播技术…

Linux环境下基本指令

今天我们一起来认识一下Linux环境下一些基本的指令&#xff0c;这些指令是我们学习Linux的基础&#xff0c;只有掌握了这些指令&#xff0c;我们才能在Linux环境下进一步学习知识&#xff0c;话不多说&#xff0c;我们开始&#xff08;以下演示操作是在云服务器的环境下&#x…

基于SSM的车位租赁系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的车位租赁系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

【数据分析之Numpy基础004】数学运算大揭秘:轻松玩转ndarray的强大实力

ndarray的数学运算是一项非常重要的操作&#xff0c;包括不同对象之间的四则运算&#xff0c;三角函数变换、求和、求平均等操作 1、四则运算 如果参与运算的两个对象都是ndarray&#xff0c;并且形状相同&#xff0c;那么就可以进行对位之间的四则&#xff08; - * / &#x…

前后端分离vue.js+nodejs学生考勤请假系统 _fbo36

此系统设计主要采用的是nodejs语言来进行开发&#xff0c;采用vue框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&#xff0c;业务处理层Service&#xff0c;持久层dao&#xff0c;能够采用多层次管理开发&#xff0c;对于各个模块设计制作有一定的安全性…

UI设计中,2D、2.5D、3D、4D该如何辨别?教会你

hello&#xff0c;我是大千UI工场&#xff0c;从事UI设计8年之久&#xff0c;在日常工作中经常听到一些概念&#xff0c;现在将这些概念图文并茂的呈现给您&#xff0c;欢迎点赞评论&#xff0c;如有设计需求&#xff0c;可以私信我们。 在UI设计中&#xff0c;2D、2.5D、3D和4…

【Pytorch深度学习开发实践学习】B站刘二大人课程笔记整理lecture09 Softmax多分类

代码&#xff1a; import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader import torch.nn as nn import torch.nn.functional as Fbatch_size 64 transform transforms.Compose([transforms.ToTensor(), transforms.Normali…

python:读 Freeplane.mm文件,使用 xml.etree 生成测试案例.csv文件

Freeplane 是一款基于 Java 的开源软件&#xff0c;继承 Freemind 的思维导图工具软件&#xff0c;它扩展了知识管理功能&#xff0c;在 Freemind 上增加了一些额外的功能&#xff0c;比如数学公式、节点属性面板等。 强大的节点功能&#xff0c;不仅仅节点的种类很多&#xf…

不用加减乘除做加法

1.题目&#xff1a; 写一个函数&#xff0c;求两个整数之和&#xff0c;要求在函数体内不得使用、-、*、/四则运算符号。 数据范围&#xff1a;两个数都满足 −10≤&#xfffd;≤1000−10≤n≤1000 进阶&#xff1a;空间复杂度 &#xfffd;(1)O(1)&#xff0c;时间复杂度 &am…

web安全学习笔记【13】——信息打点(3)

信息打点-JS架构&框架识别&泄漏提取&API接口枚举&FUZZ爬虫&插件项目[1] #知识点&#xff1a; 1、业务资产-应用类型分类 2、Web单域名获取-接口查询 3、Web子域名获取-解析枚举 4、Web架构资产-平台指纹识别 ------------------------------------ 1、开源…

2.5G/5G/10G高速率网络变压器(网络隔离变压器)产品介绍(1)

Hqst华轩盛(石门盈盛)电子导读&#xff1a;高速率/2.5G 的带POE插件&#xff08;DIP&#xff09;款千兆双口网络变压器2G54801DP特点 一 ﹑2.5G高速率网络变压器&#xff08;网络隔离变压器&#xff09;&#xff1a;2G54801DP外观与尺寸 2G54801DP这颗产品尺寸为&#xff1a;长…

C++ 学习(1)---- 左值 右值和右值引用

这里写目录标题 左值右值左值引用和右值引用右值引用和移动构造函数std::move 移动语义返回值优化移动操作要保证安全 万能引用std::forward 完美转发传入左值传入右值 左值 左值是指可以使用 & 符号获取到内存地址的表达式&#xff0c;一般出现在赋值语句的左边&#xff…

【Python笔记-设计模式】装饰器模式

一、说明 装饰器模式是一种结构型设计模式&#xff0c;旨在动态的给一个对象添加额外的职责。 (一) 解决问题 不改变原有对象结构的情况下&#xff0c;动态地给对象添加新的功能或职责&#xff0c;实现透明地对对象进行功能的扩展。 (二) 使用场景 如果用继承来扩展对象行…

数据结构-二分搜索树(Binary Search Tree)

一,简单了解二分搜索树 树结构: 问题:为什么要创造这种数据结构 1,树结构本身是一种天然的组织结构,就好像我们的文件夹一样,一层一层的. 2,树结构可以更高效的处理问题 二,二分搜索树的基础 1、二叉树 2,二叉树的重要特性 满二叉树 总结: 1. 叶子结点出现在二叉树的最…