当前位置: 首页 > news >正文

文件上传和下载(原生JS + SpringBoot实现)

目录

概述

前端编写-上传表单和图片回显

 HTML表单代码 

 发送请求逻辑

 CSS代码 

后端编写-文件上传接口

后端编写-文件下载接口


概述

在现代Web应用程序中,文件上传和下载是常见的功能。本博客将介绍如何使用原生JS和Spring Boot实现文件上传和下载的功能。

在其中会介绍到前端使用表单做文件上传时需要遵循的规则,并使用SpringBoot框架编写后端API接口来处理传入的文件,以及使用原生JS和SpringBoot框架实现文件下载功能。

测试:本篇博客主要使用图片的上传和回显作为重点测试介绍。

目的:实现类似头像上传功能效果。

整体功能逻辑:前端上传图片,后端接收到后存储到本地服务器并返回给前端存储的文件名,前端想要获取(下载)图片时,发送请求携带文件名,后端接收到后以流的方式响应给前端做展示。

前端编写-上传表单和图片回显

功能界面展示

选择并提交图片回显后展示

 HTML表单代码 

// 表单容器
<div id="container"><form id="myForm" method="post" enctype="multipart/form-data"><input type="file" name="file" id="file"><br><br><input type="submit" value="上传文件"></form>
</div>
<br>
<!-- 图片回显 -->
<div id="pictureEcho"></div>

代码说明

想要实现文件上传,表单书写时基本的3点要求

【1】请求方式method需要为post

【2】表单数据的编码类型enctypemultipart/form-data

【3】需要一个类型typefile的控件<input>上传文件

 发送请求逻辑

<script>// 获取表单节点let form = document.getElementById('myForm');// 获取图片回显容器节点let pictureEchoContainer = document.querySelector("#pictureEcho");// 监听表单的submit提交事件form.addEventListener('submit', function(event) {// submit事件触发时阻止默认事件,防止页面跳转刷新event.preventDefault();// 创建xhr对象,用于发送请求var xhr = new XMLHttpRequest();// 指定请求方式和请求路径xhr.open('POST', '/files/upload');// 使用formData对象处理表单数据var formData = new FormData(form);// 上传完成后的处理xhr.onload = function() { // 响应状态码为200表示请求成功if (xhr.status === 200) {// 调用图片回显的回调函数,将返回的随机UUID名称作为参数pictureShowCallback(xhr.responseText);}};// 发送HTTP请求并将数据发送给服务器xhr.send(formData);});// 自定义回调函数 function pictureShowCallback(pictureName){// 创建img节点let img = document.createElement("img")// 将img节点添加到div容器中 pictureEchoContainer.append(img)// 给img节点添加src属性img.src = "http://127.0.0.1:8080/files/download/" + pictureName;}
</script>

代码说明

 具体步骤说明在代码示例中已有详解,主要过程为当点击了提交按钮,触发submit事件后,会向指定服务器发送请求,并且编写了获取服务器返回值的代码,当请求成功后调用自定义回调函数,在其中动态创建img节点,并向img节点中设置src属性为请求路径。当img节点有了src属性后,会向其src的值发送请求获取图片自动展示。

其中的xhr.onload为请求完成时调用的函数,在此用于接收返回值,获取上传后服务器给图片随机生成的UUID名称,下面做图片回显(文件下载)的时候就可以根据此UUID名称发送请求了。

 CSS代码 

#container{border: solid #253bbd 2px;border-radius: 5px;width: 190px;height: 90px;padding: 20px;background-color: #6a9cd3;
}img{position: absolute;width: 230px;height: 130px;top: 10px;left: 10px;border-radius: 5px;/*border: solid red;*/
}

后端编写-文件上传接口

当我们在前端编写完请求发送逻辑以后,我们就需要有一个后端接口来接收处理发送过来的请求数据。

/*** Date:2023/3/6* author:zmh* description:文件上传和下载相关接口**/
@RestController
@RequestMapping("/files")
public class FileUploadController {// 指定文件保存的根目录private final String UPLOAD_DIR = "D:\\tmp\\img\\";/*** 文件上传接口* @param file 前端传入的文件对象* @return 返回存在服务器的文件名称*/@PostMapping("/upload")public String fileUpload(@RequestParam("file") MultipartFile file){// 获取上传的图片文件后缀名String originalFilename = file.getOriginalFilename();String fileExtension = originalFilename.substring(originalFilename.lastIndexOf('.'));// 检查文件是否为空if (file.isEmpty()) {return "File is empty!";}// 检查文件名是否合法,避免目录遍历攻击String fileName = StringUtils.cleanPath(originalFilename);if (fileName.contains("..")) {return "Illegal name!";}try {// 给上传的图片随机生成一个名称,将之返回,// 用户就可以根据此名称下载图片,防止图片名称冲突。UUID uuid = UUID.randomUUID();String randomUUIDString = uuid.toString();// 将文件保存到指定目录文件File targetFile = new File(UPLOAD_DIR + randomUUIDString + fileExtension);// 将传入的图片转存到指定目录文件file.transferTo(targetFile);// 返回随机名称(带有后缀名)return randomUUIDString + fileExtension;} catch (IOException e) {e.printStackTrace();return "server error!";}}

 代码说明 

具体步骤详解在代码注释中说明,其中重点就是动态获取UUID和传入文件的后缀名进行拼接,拼接后作为转存文件名,将传入文件转存在本地服务器目录文件中。并将拼接后的文件名返回给前端,以后,前端就可以根据此随机名来向服务器请求文件,防止了上传文件名时冲突的问题。

后端编写-文件下载接口

 为前端提供文件(图片)下载接口,当前端请求此接口时,携带路径参数(文件名)访问接口,接口将向前端响应

// 指定文件下载时服务器存储文件的根目录
private final String DOWNLOAD_DIR = "D:\\tmp\\img\\";
/*** 文件下载** @param fileName 文件名,其中的.+为正则表达式,表示可以匹配任意后缀的文件* @param response 响应*/
@GetMapping("/download/{fileName:.+}")
public void fileDownLoad(@PathVariable String fileName, HttpServletResponse response) {// 检查文件名是否合法,防止目录遍历攻击if (fileName.contains("..")) {// 文件名不合法,响应给前端状态400,表示错误请求response.setStatus(HttpServletResponse.SC_BAD_REQUEST);return;}try {// 获取输入流读取本地文件FileInputStream fileInputStream = new FileInputStream(new File(DOWNLOAD_DIR + fileName));// 获取输出流,用于向前端输出文件图片ServletOutputStream outputStream = response.getOutputStream();// 指定响应内容类型response.setContentType("image/jpg");// 遍历流输出操作int len = 0;byte[] bytes = new byte[1024];// 使用一个字节数组存容量为1024作为一组数据// 循环读取文件中数据,当读取到的数据不等于-1时代表依然有数据while((len = fileInputStream.read(bytes)) != -1){// 将存储在bytes数组中的数据写出outputStream.write(bytes, 0, len);// 手动刷洗输出流,不必等到存满在输出outputStream.flush();}// 关闭流资源fileInputStream.close();outputStream.close();} catch (Exception e) {throw new RuntimeException(e);}
}

相关文章:

文件上传和下载(原生JS + SpringBoot实现)

目录 概述 前端编写-上传表单和图片回显 HTML表单代码 发送请求逻辑 CSS代码 后端编写-文件上传接口 后端编写-文件下载接口 概述 在现代Web应用程序中&#xff0c;文件上传和下载是常见的功能。本博客将介绍如何使用原生JS和Spring Boot实现文件上传和下载的功能。 在其…...

【C语言学习笔记】:安全性

用const修饰变量或方法&#xff0c;从而告诉编译器这些都是不可变的&#xff0c;有助于编译器优化代码&#xff0c;并帮助开发人员了解函数是否有副作用。此外&#xff0c;使用const &可以防止编译器复制不必要的数据。John Carmack对const的评论[2]值得一读。 // Bad Ide…...

Linux - 磁盘存储管理 磁盘引入

# 我们要介绍下 磁盘管理&#xff0c; 那不妨先来看一张图来简单 引入 &#xff1a;这张图呢&#xff0c;是我们 Windows 上的磁盘管理的显示 。根据这幅图呢&#xff0c;提出一个问题 &#xff1a;>>> 这幅图磁盘管理所显示的内容&#xff0c;你能判断出 该电脑 有几…...

分割std::string成多个string

文章目录问题描述前置知识解决代码问题描述 假设我们有一个http服务器&#xff0c;此服务器接收客户端发来的http请求&#xff0c;假设请求如下 GET / HTTP/1.1我们怎么将这个Http请求分割成三份&#xff0c;分别存入不同的string中分别处理? 前置知识 首先std::string的本…...

3月多国更新进出口产品规定

【3月多国更新进出口产品规定】2023年3月多项外贸新规实施&#xff0c;涉及欧盟&#xff0c;伊拉克&#xff0c;泰国&#xff0c;孟加拉国&#xff0c;埃及等多国进出口产品限制及海关税则。1. 3月1日起给予埃塞俄比亚等三国98%税目产品零关税待遇中国国务院关税税则委员会17日…...

nacos相关面试题

Nacos是阿里巴巴开源的一款注册中心和配置中心&#xff0c;它能够实现服务的注册、发现和配置管理等功能。Nacos的实现原理主要分为以下几个部分&#xff1a;注册中心&#xff1a;Nacos作为注册中心&#xff0c;通过提供RESTful API的方式对外提供注册和发现服务。它使用基于Ra…...

Linux基础命令-groupmems管理组群的成员

Linux-usermod修改用户 Linux-useradd创建用户 Linux-userdel删除用户 Linux基础命令-chown修改文件属主 Linux基础命令-chmod修改文件权限 groupmems 命令介绍 先来看看这个命令的帮助信息是什么概念 NAME groupmems - administer members of a user’s primary group group…...

css系统化学习

元素的语义化 SEO:搜索引擎优化 根据搜索引擎展示的规律,语义化的元素更容易被展示获得更多浏览量 字符编码 css历史 内联样式(inline) style"内容全写在等号后面,双引号里面,多个之间用;隔开" 内部样式(internal) style写在head里面,在title下面,不是在body内, …...

AI的简单介绍

什么是AI&#xff1f; AI 是 Artificial Intelligent 的缩写&#xff0c;是我们通常意义上说的人工智能。 简单来说就是让机器能够模拟人类的思维能力&#xff0c;让它能够像人一样感知、思考甚至决策。 为什么要开发AI&#xff1f; 因为在过去&#xff0c;都是我们学习机器…...

【Linux】-- 进程间通讯

目录 进程间通讯概念的引入 意义&#xff08;手段&#xff09; 思维构建 进程间通信方式 管道 站在用户角度-浅度理解管道 匿名管道 pipe函数 站在文件描述符角度-深度理解管道 管道的特点总结 管道的拓展 单机版的负载均衡 匿名管道读写规则 命名管道 前言 原理…...

STM32模拟SPI时序控制双路16位数模转换(16bit DAC)芯片DAC8552电压输出

STM32模拟SPI时序控制双路16位数模转换&#xff08;16bit DAC&#xff09;芯片DAC8552电压输出 STM32部分芯片具有12位DAC输出能力&#xff0c;要实现16位及以上DAC输出需要外挂DAC转换ASIC。 DAC8552是双路16位DAC输出芯片&#xff0c;通过SPI三线总线进行配置控制输出。这里…...

基于intel x86+fpga智能驾驶舱和高级驾驶辅助系统硬件设计(二)

系统功能架构及各模块功能介绍 智能驾驶舱和高级驾驶辅助系统是一个车载智能终端嵌入式平台&#xff0c;系统是一个能够运行 虚拟化操作系统的软件和硬件的综合体。本文的车载主机包括硬件主控处理器、电源管理芯 片、存储设备、输入输出控制器、数字仪表系统系统、后座娱乐系统…...

oneblog_justauth_三方登录配置【Github】

文章目录oneblog添加第三方平台github中创建三方应用完善信息登录oneblog添加第三方平台 1.oneblog管理端&#xff0c;点击左侧菜单 网站管理——>社会化登录配置管理 ,添加一个社会化登录 2.编辑信息如下&#xff0c;选择github平台后复制redirectUri,然后去github获取cl…...

自行车轮胎充气泵PCBA方案

轮胎充气泵PCBA方案由多种元器件设计组合而成&#xff0c;PCBA是英文Printed Circuit Board Assembly 的简称&#xff0c;也就是说PCB空板经过SMT上件&#xff0c;或经过DIP插件的整个制程&#xff0c;简称PCBA。PCBA是一个电子产品功能实现的最原始的状态&#xff0c;未经过任…...

200 22222

101. blob.png 新到组织的项目经理被分配管理一个具有多名干系人的项目。项目经理希望确定哪些干系人是内部的&#xff0c;哪些干系人是外部的。若要了解干系人的角色&#xff0c;项目经理应该查阅哪一份文件&#xff1f; A. 干系人登记册 B. 干系人分析 C. 干系人管理计划 D.…...

<JVM上篇:内存与垃圾回收篇>13 - 垃圾回收器

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录13.1. GC 分类与性能指标13.1.1. 垃圾回收器概述13.1.2. 垃圾收集器分类13.1.3. 评估 GC 的性能指标13.2. 不同的垃圾回收器概述13.…...

广义状态平均法功率变换器建模分析

两种状态平均法在功率变换器建模的应用比较 [!info] Bibliography [1] 高朝晖, 林辉张晓斌 & 吴小华, “两种状态平均法在功率变换器建模的应用比较,” 计算机仿真, no. 241-244248, 2008. [!note] 状态空间平均法采用直流量近似&#xff08;线性系统模型&#xff09;&…...

基于Spring Boot的快递管理系统

文章目录 项目介绍主要功能截图:登录我要收件我要寄件个人信息我收到的我寄出的物流管理用户管理部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项…...

nerdctl不完全使用指南(开发者)

目录 背景 环境配置 1.编译golang可执行文件 2.快速构建镜像 背景 k8s在1.22版本放弃docker作为runtime后采用了containerd&#xff0c;以containerd作为runtime的k8s安装方法已经出现了很多开源集成工具或者解决方案&#xff0c;在此不做赘述。本篇只要是描述在docker被取…...

【独家】华为OD机试 - 分糖果(C 语言解题)

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...