vue+Springboot实现简单文件上传到本地

实现效果

点击上传文件按钮后,选择需要上传的文件,如果是图片的话,上传成功后可以直接在下面预览。

前端页面

<template><div class="file-upload"><el-upload:headers="getUploadConfig(token).headers"action="http://localhost:1011/api/user/file/upload":on-success="handleSuccess"list-type="picture"v-model:file-list="fileList"><el-button size="small" type="primary"> 上传文件 </el-button></el-upload><div class="demo-image__preview"><el-imagestyle="width: 100px; height: 100px; border-radius: 50%":src="url":preview-src-list="[url]"fit="cover"/></div></div>
</template><script setup>
import { ref } from "vue";
import { useTokenStore } from "@/stores/token";const url = ref("");
const fileList = ref([]);
const tokenStore = useTokenStore();// 这里暂时保留从localStorage获取token的方式,但这是不安全的,仅用于示例
const token = ref("");
try {const storedToken = JSON.parse(localStorage.getItem("token"));if (storedToken && storedToken.token) {token.value = storedToken.token;}
} catch (error) {console.error("Error parsing token from localStorage:", error);
}const getUploadConfig = () => {const token = tokenStore.token;return {headers: {Authorization: token,},};
};const handleSuccess = (response, file, fileList) => {fileList.value = fileList;console.log("上传成功,响应内容:", response);console.log("上传的文件:", file);console.log("更新后的文件列表:", fileList);console.log("当前文件列表:", fileList.value);url.value = response.data;// 处理非成功情况console.log("当前文件列表:", url.value);
};
</script><style scoped>
.file-upload {max-width: 400px;margin: auto;padding: 20px;border: 1px solid #ccc;border-radius: 5px;
}
.demo-image__error .image-slot {font-size: 30px;
}
.demo-image__error .image-slot .el-icon {font-size: 30px;
}
.demo-image__error .el-image {width: 100%;height: 200px;
}
</style>

主要代码详细解释: 

<el-upload:headers="getUploadConfig(token).headers"action="http://localhost:1011/api/user/file/upload":on-success="handleSuccess"list-type="picture"v-model:file-list="fileList"
><el-button size="small" type="primary">上传文件</el-button>
</el-upload>
  • el-upload组件:这是基于 Element Plus 库的文件上传组件。
    • :headers:绑定了一个通过getUploadConfig(token)函数获取的请求头对象,其中包含了Authorization信息(可能用于后端的身份验证)。
    • action:指定了文件上传的目标 URL,即后端处理文件上传的接口地址,需要根据自己项目情况填写。
    • :on-success:绑定了handleSuccess函数,当文件上传成功时会触发该函数。
    • list-type="picture":设置文件列表的类型为图片形式,这可能会影响文件在界面上的显示样式(比如显示图片缩略图)。
    • v-model:file-list="fileList":使用v-model双向绑定文件列表数据,fileList是一个在script部分定义的响应式数据,用于存储已选择的文件信息。
    • 内部的el-button是触发文件选择和上传的按钮。
<div class="demo-image__preview"><el-imagestyle="width: 100px; height: 100px; border-radius: 50%":src="url":preview-src-list="[url]"fit="cover"/>
</div>
  • 这部分用于显示上传成功后的文件预览(这里假设是图片)。el-image组件用于显示图片,它的src属性绑定了url(在script部分定义的响应式数据),preview-src-list也使用了url,这样当用户点击图片时可以进行预览。style属性设置了图片的尺寸和样式(圆形,宽高为 100px),fit="cover"表示图片填充方式。
const token = ref("");
try {const storedToken = JSON.parse(localStorage.getItem("token"));if (storedToken && storedToken.token) {token.value = storedToken.token;}
} catch (error) {console.error("Error parsing token from localStorage:", error);
}

这段代码从localStorage中获取token信息。首先从localStorage中获取token字符串,然后解析为对象并检查是否存在token属性,如果有则将其赋值给token响应式数据。 

const getUploadConfig = () => {const token = tokenStore.token;return {headers: {Authorization: token,},};
};
  • 这个函数用于获取文件上传的请求头配置。它从tokenStore中获取token,并返回一个包含Authorization头的对象,用于在文件上传请求中传递身份验证信息给后端。(这里是用于权限鉴定的,将token信息以Authorization头的形式传给后端,然后没有token可以省略这个代码)
const handleSuccess = (response, file, fileList) => {fileList.value = fileList;url.value = response.data;};

 handleSuccess函数:这是文件上传成功的回调函数。

  • 首先将传入的fileList赋值给fileList.value,以更新本地存储的文件列表数据。
  • response.data赋值给url.value,这意味着如果后端在成功响应中返回了文件的访问地址(比如图片的 URL),则将其存储在url中,用于在界面上显示文件预览。

 后端代码

在 Spring Boot 项目中创建一个控制器(Controller)来处理文件上传和下载请求,例如FileController.java。 

 

import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.IOException;@RestController
public class FileUploadController {// 上传文件的方法,与之前代码相同@PostMapping("/upload")public String uploadFile(@RequestParam("file") MultipartFile file) {if (!file.isEmpty()) {try {// 设置文件保存的路径,这里假设保存到项目的一个upload目录下String filePath = "upload/" + file.getOriginalFilename();File dest = new File(filePath);file.transferTo(dest);return "文件上传成功";} catch (IOException e) {e.printStackTrace();return "文件上传失败:" + e.getMessage();}} else {return "请选择要上传的文件";}}// 下载文件的方法@GetMapping("/download/{filename}")public ResponseEntity<FileSystemResource> downloadFile(@PathVariable("filename") String filename) {// 根据文件名构建文件对象,假设文件保存在项目的upload目录下File file = new File("upload/" + filename);if (file.exists()) {// 创建一个FileSystemResource对象,用于包装要下载的文件FileSystemResource resource = new FileSystemResource(file);// 设置响应头,包括文件名和文件类型等信息HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "attachment; filename=" + filename);headers.add("Cache-Control", "no-cache, no-store, must-revalidate");headers.add("Pragma", "no-cache");headers.add("Expires", "0");// 根据文件类型设置Content-TypeMediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {mediaType = MediaType.IMAGE_JPEG;} else if (filename.endsWith(".png")) {mediaType = MediaType.IMAGE_PNG;} else if (filename.endsWith(".pdf")) {mediaType = MediaType.APPLICATION_PDF;}headers.setContentType(mediaType);// 返回一个ResponseEntity对象,包含文件资源、响应头和状态码200,表示下载成功return ResponseEntity.ok().headers(headers).body(resource);} else {// 如果文件不存在,返回一个状态码为404的ResponseEntity对象,表示文件未找到return ResponseEntity.notFound().build();}}
}

在上述代码中:

  1. downloadFile方法接受一个@PathVariable注解的参数filename,用于指定要下载的文件名。
  2. 根据文件名构建了对应的文件对象,并检查文件是否存在。
  3. 如果文件存在,创建了FileSystemResource对象来包装要下载的文件,并设置了一系列响应头信息,包括Content-Disposition用于指定下载时的文件名(确保客户端能以正确的文件名保存下载的文件),以及Cache-ControlPragmaExpires等用于控制缓存的信息。同时,根据文件的后缀名设置了合适的Content-Type
  4. 最后,返回一个ResponseEntity对象,其中包含了文件资源、设置好的响应头和状态码200,表示下载成功。如果文件不存在,则返回一个状态码为404ResponseEntity对象,表示文件未找到。

这样,客户端就可以通过访问/download/{filename}这个接口来下载指定的文件了。例如,如果上传了一个名为test.jpg的文件,客户端可以通过访问/download/test.jpg来下载该文件。

 

 

 

 

 

 

 

 

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

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

相关文章

解决 Vue3、Vite 和 TypeScript 开发环境下跨域的问题,实现前后端数据传递

引言 本文介绍如何在开发环境下解决 Vite 前端&#xff08;端口 3000&#xff09;和后端&#xff08;端口 80&#xff09;之间的跨域问题&#xff1a; 在开发环境中&#xff0c;前端使用的 Vite 端口与后端端口不一致&#xff0c;会产生跨域错误提示&#xff1a; Access to X…

Java项目实战II基于微信小程序的订餐系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导 一、前言 随着移动互联网技术的飞速发展&#xff0…

闯关leetcode——202. Happy Number

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/happy-number/description/ 内容 Write an algorithm to determine if a number n is happy. A happy number is a number defined by the following process: Starting with any positive inte…

昇思大模型平台打卡体验活动:项目4基于MindSpore实现Roberta模型Prompt Tuning

基于MindNLP的Roberta模型Prompt Tuning 本文档介绍了如何基于MindNLP进行Roberta模型的Prompt Tuning&#xff0c;主要用于GLUE基准数据集的微调。本文提供了完整的代码示例以及详细的步骤说明&#xff0c;便于理解和复现实验。 环境配置 在运行此代码前&#xff0c;请确保…

中国药品注册审批数据库- 药品注册信息查询与审评进度查询方法

药品的注册、审评审批进度信息是医药研发相关人员每天都会关注的信息&#xff0c;为了保证药品注册申请受理及审评审批进度信息的公开透明&#xff0c;CDE药审中心提供药品不同注册分类序列及药品注册申请受理的审评审批进度信息查询服务。但因CDE官网的改版导致很大一部分人不…

FMC 扩展子卡6 路 422,8 组 LVDS,8 路 GPIO

FMC 扩展子卡6 路 422,8 组 LVDS,8 路 GPIO 卡是一款支持多路 LVCMOS 和 LVDS 信号互转的 FMC 扩展子板。它能支持 6 路 422 信号的输入 / 输出 ,8 组 LVDS 信号的输入 / 输出和 8 路 GPIO 信号的输入 / 输出。本产品基于一些逻辑转换芯片而设计&#xff0c;能实现差分信号转单…

C++builder中的人工智能(21):Barabási–Albert model(BA)模型

在此之前&#xff0c;大多数网络被想当然的认为是随机的&#xff0c;因此连接度分布可以近似用泊松分布来表示&#xff0c;而巴拉巴西与其学生阿尔伯特、郑浩雄通过对万维网度分布测量的结果却显示万维网度分布服从幂律分布&#xff0c;存在枢纽节点&#xff08;拥有大量链接的…

MyBatis3-获取参数值的方式、查询功能及特殊SQL执行

目录 准备工作 获取参数值的方式&#xff08;重点&#xff09; 查询功能 查询一个实体类对象 查询一个list集合 查询单个数据 查询一条数据为map集合 查询多条数据为map集合 特殊SQL执行 模糊查询 批量删除 动态设置表名 添加功能获取自增的主键 准备工作 模块My…

链表(Linkedlist)

序言 我们都了解链表是一种数据的存储结构&#xff0c;在Java使用中逻辑与c&#xff0c;c语言数据结构别无二致&#xff0c;但主要由于Java中不存在指针的说法&#xff0c;从而导致在实现过程中的代码不同&#xff0c;所以在学习的过程中我们无需过于担心&#xff0c;逻辑都是…

【分布式事务】二、NET8分布式事务实践: DotNetCore.CAP 框架 、 消息队列(RabbitMQ)、 多类型数据库(MySql、MongoDB)

介绍 DotNetCore.CAP简称CAP, [CAP]是一个用来解决微服务或者分布式系统中分布式事务问题的一个开源项目解决方案, 同样可以用来作为 EventBus 使用,CAP 拥有自己的特色,它不要求使用者发送消息或者处理消息的时候实现或者继承任何接口,拥有非常高的灵活性。我们一直坚信…

利用pythonstudio写的PDF、图片批量水印生成器,可同时为不同读者生成多组水印

现在很多场合需要将PDF或图片加水印&#xff0c;本程序利用pythonstudio编写。 第一步 界面 其中&#xff1a; LstMask:列表框 PopupMenu:PmnMark LstFiles:列表框 PopupMenu:PmnFiles OdFiles:文件选择器 Filter:PDF文件(.PDF)|.PDF|图像文件(.JPG)|.JPG|图像文件(.png…

面试:TCP、UDP如何解决丢包问题

文章目录 一、TCP丢包原因、解决办法1.1 TCP为什么会丢包1.2 TCP传输协议如何解决丢包问题1.3 其他丢包情况&#xff08;拓展&#xff09;1.4 补充1.4.1 TCP端口号1.4.2 多个TCP请求的逻辑1.4.3 处理大量TCP连接请求的方法1.4.4 总结 二、UDP丢包2.1 UDP协议2.1.1 UDP简介2.1.2…

Python的函数(补充浅拷贝和深拷贝)

一、定义 函数的定义&#xff1a;实现【特定功能】的代码块。 形参&#xff1a;函数定义时的参数&#xff0c;没有实际意义 实参&#xff1a;函数调用/使用时的参数&#xff0c;有实际意义 函数的作用&#xff1a; 简化代码提高代码重用性便于维护和修改提高代码的可扩展性…

Spring Boot框架的知识分类技术解析

2 开发技术 2.1 VUE框架 Vue.js&#xff08;读音 /vjuː/, 类似于 view&#xff09; 是一套构建用户界面的渐进式框架。 Vue 只关注视图层&#xff0c; 采用自底向上增量开发的设计。 Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 2.2 Mysql数据库 …

Hive详解

1 Hive基本概念 Hive是一个构建在Hadoop上的数据仓库框架。最初&#xff0c;Hive是由Facebook开发&#xff0c;后来移交由Apache软件基金会开发&#xff0c;并作为一个Apache开源项目。 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据…

llamaIndex和langchain对比及优劣对比

一. LangChain vs LlamaIndex: 基本描述 LlamaIndex在搜索和检索任务方面表现出色。它是一个强大的数据索引和查询工具&#xff0c;非常适合需要高级搜索的项目。LlamaIndex能够处理大型数据集&#xff0c;从而实现快速准确的信息检索。 LangChain是一个模块化和灵活的工具集框…

《重学Java设计模式》之 工厂方法模式

《重学Java设计模式》之 建造者模式 《重学Java设计模式》之 原型模式 《重学Java设计模式》之 单例模式 模拟发奖多种商品 工程结构 奖品发放接口 package com.yys.mes.design.factory.store;public interface ICommodity {/*** Author Sherry* Date 14:20 2024/11/6**/voi…

【C++笔记】string类的模拟实现

前言 各位读者朋友们大家好&#xff01;上期我们讲解了string类的基础用法&#xff0c;这期我们来模拟实现一下string类。 目录 前言一. string类的构造函数1. 1 无参构造2.2 带参构造1.3 无参和带参构造结合1.4 拷贝构造1.5 c_str 二. string类的析构函数三. 字符串的遍历3.…

java中ArrayList的使用存储对象的易错点

ArrayList存储对象的易错点 上面这种写法是有逻辑问题的&#xff0c;因为只创建了一个Student对象&#xff0c;因此最后打印出来的结果是三个最后赋值的结果。 下面我们来形象看下存储关系 集合中存储的始终是第一个对象的地址&#xff0c;而每次输入新的名字和年龄&#xf…

栈和队列(Java)

一.栈&#xff08;Stack&#xff09; 1.定义 栈是限定仅在表尾进行插入或删除操作的线性表 一般的表尾称为栈顶 表头称为栈底 栈具有“后进先出”的特点 2.对栈的模拟 栈主要具有以下功能&#xff1a; push(Object item)&#xff1a;将元素item压入栈顶。 pop()&am…