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.xdnf.cn/news/12318.html

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

相关文章

闯关leetcode——3206. Alternating Groups I

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/alternating-groups-i/description/ 内容 There is a circle of red and blue tiles. You are given an array of integers colors. The color of tile i is represented by colors[i]: colors[i…

QT Unknown module(s) in QT 以及maintenance tool的更详细用法(qt6.6.0)

不小心接了同事的委托&#xff0c;帮改一个qt的工程代码。然后出事了&#xff0c;那个proj是qt5.9版本的吧&#xff0c;搞到6.6版本的环境中各种问题。至少有3个是这样的&#xff1a; :-1: error: Unknown module(s) in QT: multimedia 直接百度&#xff0c;好像很简单&#x…

Springboot苍穹外卖实战:四、分页查询(PageHelper实现、日期格式转换)

分页查询 使用PageHelper插件实现。其实可以升级为MybatisPlus的。 接口设计 设计DTO类 com.sky.dto.EmployeePageQueryDTO 已设计好&#xff0c;为EmployeePageQueryDTO&#xff1b; 封装PageResult com.sky.result.PageResult com.sky.result.Result 已封装好&#xff0…

0x00基础算法 -- 0x03 前缀和与差分

1、前缀和 对于一个给定的数组A&#xff0c;它的前缀和数列S是通过递推求得的&#xff1a;//A[]和S[]的有效数据从下标1开始&#xff0c;方便后续计算 s[0] 0; for (int i 1; i < n; i) {s[i] s[i - 1] A[i]; } 作用&#xff1a;用于快速求得某一部分的和&#xff1a;对…

四焦距聚焦型光场计算成像系统的设计

摘要: 光场相机是一种在图像传感器前增加微透镜阵列的新型相机结构&#xff0c;除了记录不同位置下光的强度及颜色外&#xff0c;也记录不同位置下光线的方向信息&#xff0c;从而能够计算目标场景的深度图和高阶相位图。该技术由于景深和分辨率相互制约&#xff0c;获得大景深…

ubuntu18.04 配置安卓编译环境

目前有个项目&#xff0c;验收时有个要求是在linux中进行编译打包生成apk文件。我平时都是在windows环境android studio中进行打包的&#xff0c;花了半天时间研究了一下&#xff0c;记录如下&#xff1a; 安装安卓sdk cd /opt wget https://dl.google.com/android/reposito…

qt QWidgetAction详解

1、概述 QWidgetAction是Qt框架中的一个类&#xff0c;它继承自QAction类。QWidgetAction允许开发者将自定义的小部件&#xff08;widget&#xff09;插入到基于QAction的容器中&#xff0c;如工具栏或菜单项中。这使得QWidgetAction成为创建复杂用户界面和自定义菜单项的强大…

工位管理革新:Spring Boot企业级系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理企业级工位管理系统的相关信息成为必然。开…

mysql查询语句(基础)

查询所需要的关键字 select 先在图形化工具导入数据库文件。 1&#xff1a;查询一个表中的所有列&#xff0c;使用通配符 * 。 select * from 表名 ; 2&#xff1a;查询表中的某列字段。 select 字段1,字段2,... from 表名; 字段之间使用逗号隔开。 …

Zookeeper的安装与使用

一、简介 1.1、概念 ZooKeeper 是一个开源的分布式协调服务&#xff0c;主要用于解决分布式系统中的数据一致性问题。它提供了一种可靠的机制来管理和协调分布式系统的各个节点。ZooKeeper 的设计目标是简化分布式应用的开发&#xff0c;提供简单易用的接口和高性能、高稳定性…

【论文阅读】医学SAM适配器:适应医学图像分割的任意分割模型

【论文阅读】医学SAM适配器&#xff1a;适应医学图像分割的任意分割模型 文章目录 【论文阅读】医学SAM适配器&#xff1a;适应医学图像分割的任意分割模型一、介绍二、联系工作三、方法四、实验 Medical SAM Adapter: Adapting Segment Anything Model for Medical Image Segm…

caozha-ip(IP地址查询源码)

caozha-ip&#xff0c;是基于原生PHP写的一套完整的IP转地址模块源码&#xff0c;支持自动获取IP&#xff0c;也支持查询指定IP&#xff0c;同时支持输出json、jsonp、text、xml、js等多种IP和地址格式&#xff0c;还可以细分为国家、省、市、地区&#xff0c;方便在各种系统里…

【Android、IOS、Flutter、鸿蒙、ReactNative 】文本Text显示

XML布局 参考 android:text <TextViewandroid:id"id/textview"android:layout_width"wrap_content"android:layout_height"wrap_content"android:text"Android Java TextView"app:layout_constraintBottom_toBottomOf"paren…

FPGA学习笔记#7 Vitis HLS 数组优化和函数优化

本笔记使用的Vitis HLS版本为2022.2&#xff0c;在windows11下运行&#xff0c;仿真part为xcku15p_CIV-ffva1156-2LV-e&#xff0c;主要根据教程&#xff1a;跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习 学习笔记&#xff1a;《FPGA学习笔记》索引 FPGA学习笔记#1 HLS简介及…

深入浅出JUC常用同步器

文章目录 1.JUC下同步器1.1 CountdownLatch 倒计数锁存器1.2 CyclicBarrier回环屏障1.3 Semephone 信号量 2.小结 1.JUC下同步器 日常开发会遇到主线程开启多个子线程去并行执行任务&#xff0c;并且主线程需要等待所有子线程执行完后在进行汇总的场景。 同步器出现之前&…

工位管理新策略:Spring Boot企业级应用

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

CAN总线物理层特性详细分析

目录 1. 简介 2. CAN总线拓扑图 3. CAN硬件电路 4. CAN电平标准 5. CAN收发器-TJA1050&#xff08;高速CAN&#xff09; 6. CAN物理层特性 1. 简介 CAN总线&#xff08;Controller Area Network Bus&#xff09;控制器局域网总线&#xff0c;是由BOSCH公司开发的一…

2024AAAI | DiffRAW: 利用扩散模型从手机RAW图生成单反相机质量的RGB图像

文章标题&#xff1a;《DiffRAW: Leveraging Diffusion Model to Generate DSLR-Comparable Perceptual Quality sRGB from Smartphone RAW Images》 原文链接&#xff1a;DiffRAW 本文是清华大学深圳研究院联合华为发表在AAAI-2024上的论文&#xff08;小声bb&#xff1a;华…

idea出现的问题

1.idea正常的运行,但是debug失败 原因&#xff1a;debug模式中使用的jdk和你在环境变量中配置的不是同一个jdk。或者说三处地方修改一致即可 1.File/Project Structure/Project Settings/Modules中的SDK 2.File/Project Structure/Platform Settings 中的SDKS 3.Run/Debug Conf…

uni-app之数据驱动的picker选择器( uni-data-picker)之可以选择到任意级别

背景说明 uni-app 官方的插件市场有数据驱动选择器&#xff0c;可以用作多级分类的场景。本人引入插件后&#xff0c;发现&#xff0c;在h5和微信小程序都只能选择到叶子级。而在给出的官方组件示例中确并非如此。 以选择年级&#xff0c;而不选择班级。然后&#xff0c;想试试…