深圳网站网站开发/武汉搜索引擎营销
Git仓库
https://gitee.com/Lin_DH/system
介绍
从 MySQL 中,下载保存的 blob 格式的文件。
代码实现
第一步:配置文件
application.yml
spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: rootmybatis-plus:type-aliases-package: com.lm.system.commonmapper-locations: classpath:com.lm.system/mapper/*Mapper.xmlcheck-config-location: trueconfiguration:#日志实现,不配置不会输出SQL日志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
第二步:编写实体类
SysFile.java
package com.lm.system.common;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;/*** @author DUHAOLIN* @date 2024/10/17*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SysFile {@TableId(value = "id", type = IdType.INPUT)private Integer id;private String name;private String format;private byte[] data;private long size;private Date createTime;}
第三步:编写dao层接口
SysFileMapper.java
package com.lm.system.mapper;import com.baomidou.dynamic.datasource.annotation.DS;
import com.lm.system.common.SysFile;import java.util.List;/*** @author DUHAOLIN* @date 2024/10/17*/
//@DS("system")
public interface SysFileMapper {int insertFile(SysFile file);List<SysFile> queryFiles();SysFile queryFileById(Integer id);}
第四步:编写dao层实现SQL
SysFileMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lm.system.mapper.SysFileMapper"><resultMap id="files" type="com.lm.system.common.SysFile"><id property="id" column="id" jdbcType="INTEGER" /><result property="name" column="name" jdbcType="VARCHAR" /><result property="format" column="format" jdbcType="VARCHAR" /><result property="data" column="data" jdbcType="BLOB" /><result property="size" column="size" jdbcType="DOUBLE" /><result property="createTime" column="create_time" jdbcType="TIMESTAMP" /></resultMap><insert id="insertFile" parameterType="com.lm.system.common.SysFile">INSERT INTO t_file (NAME, FORMAT, DATA, SIZE)VALUES (#{name}, #{format}, #{data}, #{size})</insert><select id="queryFiles" resultMap="files">SELECT ID, NAME, FORMAT, `SIZE`, CREATE_TIMEFROM t_file</select><!-- SELECT ID, NAME, FORMAT,-->
<!-- (CASE WHEN `SIZE` <![CDATA[<]]> 1024 THEN CONCAT(`SIZE`, ' b')-->
<!-- WHEN `SIZE` <![CDATA[>=]]> 1024 AND `SIZE` <![CDATA[<]]> 1024000 THEN CONCAT(ROUND(`SIZE` / 1024, 2), ' KB')-->
<!-- WHEN `SIZE` <![CDATA[>=]]> 1024000 AND `SIZE` <![CDATA[<]]> 1024000000 THEN CONCAT(ROUND(`SIZE` / 1024000, 2), ' MB')-->
<!-- END) `SIZE`,-->
<!-- DATE_FORMAT(CREATE_TIME, '%Y-%m-%d %h:%i:%s') CREATE_TIME-->
<!-- FROM t_file--><select id="queryFileById" resultType="com.lm.system.common.SysFile">SELECT ID, NAME, FORMAT, DATA, `SIZE`, CREATE_TIMEFROM t_fileWHERE ID = #{id}</select></mapper>
第五步:编写下载页面
download.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head lang="en"><meta charset="UTF-8" /><title>文件下载页面</title><script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
<h1>文件下载页面</h1>
<table border="1"><!-- 表头 --><thead><tr><th>#</th><th>ID</th><th>文件名</th><th>格式</th><th>文件大小</th><th>创建时间</th><th>操作</th></tr></thead><!-- 表体 --><tbody><tr th:each="file,stats:${files}"><td th:text="${stats.count}"></td><td th:text="${file.id}"></td><td th:text="${file.name}"></td><td th:text="${file.format}"></td><td th:if="${file.size} < 1024" th:text="${#numbers.formatDecimal(file.size, 0, 0)} + ' b'"></td><td th:if="${file.size} >= 1024 and ${file.size} < 1024000" th:text="${#numbers.formatDecimal(file.size/1024, 0, 0)} + ' KB'"></td><td th:if="${file.size} >= 1024000 and ${file.size} < 1024000000" th:text="${#numbers.formatDecimal(file.size/1024000, 0, 0)} + ' MB'"></td><td th:text="${#dates.format(file.createTime, 'yyyy-MM-dd HH:mm:ss')}"></td><td><button th:onclick="'downloadFile(\'' + ${file.id} + '\');'">下载</button></td></tr></tbody>
</table><script th:inline="javascript">let files = [[${files}]];function downloadFile(id) {$.ajax({url: '/downloadFile/' + id,type: 'GET',responseType: 'blob',success: function (res, status, xhr) {let link = document.createElement("a");link.href = this.url;let filename = xhr.getResponseHeader("Content-Disposition").split("attachment; filename=")[1];link.setAttribute("download", filename);link.click();window.URL.revokeObjectURL(link.href); //释放内存},error: function (xhr, status, error) {console.log("error", error);}});}
</script></body>
</html>
第七步:编写文件 Controller 类
FileController.java
package com.lm.system.controller;import com.lm.system.common.SysFile;
import com.lm.system.exception.FileException;
import com.lm.system.mapper.SysFileMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;/*** @author DUHAOLIN* @date 2024/10/15*/
@Controller
public class FileController {@Resourceprivate SysFileMapper fileMapper;private final static String FILE_FORMAT_TXT = "txt";private final static String FILE_FORMAT_JPEG = "jpg";private final static String FILE_FORMAT_PNG = "png";@Value("${file.upload.path}")private String path;@GetMapping("uploadPage")public String uploadPage() {return "upload";}@PostMapping("upload")@ResponseBodypublic String upload(@RequestParam("file") MultipartFile file) throws IOException {//校验文件try {String[] fileFormats = { FILE_FORMAT_TXT };checkFile(file, fileFormats);} catch (FileException e) {e.printStackTrace();return e.getMessage();}String filename = path + file.getOriginalFilename().replace(FILE_FORMAT_TXT, "_" + System.currentTimeMillis() + FILE_FORMAT_TXT);java.io.File newFile = new java.io.File(filename);Files.copy(file.getInputStream(), newFile.toPath());return "新文件已生成," + newFile.getAbsolutePath();}private void checkFile(MultipartFile file, String[] fileFormats) {//校验文件大小checkSize(file.getSize());//校验文件名checkFilename(file.getOriginalFilename());//校验文件格式checkFileFormat(file.getOriginalFilename(), fileFormats);}private void checkSize(long size) {if (size > 10485760L) //10MBthrow new FileException("文件大于10MB");}private void checkFilename(String filename) {if (!StringUtils.hasText(filename))throw new FileException("文件名有误");}private void checkFileFormat(String filename, String[] fileFormats) {int i = filename.lastIndexOf(".");String suffix = filename.substring(i + 1); //文件后缀long c = Arrays.stream(fileFormats).filter(s -> s.equals(suffix)).count(); //判断是否存在该文件后缀if (c < 1) throw new FileException("文件格式有误,该文件类型为:" + suffix);}@GetMapping("multiFileUploadPage")public String multiFileUploadPage() {return "multiFileUpload";}@PostMapping("multiFileUpload")@ResponseBodypublic String multiFileUpload(@RequestParam("files") MultipartFile[] files) throws IOException {StringBuilder sb = new StringBuilder();for (MultipartFile file : files) {//校验文件boolean b = true;try {String[] fileFormats = new String[] { FILE_FORMAT_TXT };checkFile(file, fileFormats);} catch (FileException e) {e.printStackTrace();sb.append(file.getOriginalFilename()).append(e.getMessage()).append("<br>");b = false;}if (b) { //文件格式不对则不进行上传String filename = path + file.getOriginalFilename().replace(FILE_FORMAT_TXT, "_" + System.currentTimeMillis() + FILE_FORMAT_TXT);java.io.File newFile = new java.io.File(filename);Files.copy(file.getInputStream(), newFile.toPath());sb.append("新文件已生成,").append(newFile.getAbsolutePath()).append("<br>");}}return sb.toString();}@GetMapping("uploadToDBPage")public String uploadToDBPage() {return "uploadToDB";}@PostMapping("uploadToDB")@ResponseBodypublic String uploadToDB(@RequestParam("file") MultipartFile file) throws IOException {//校验文件try {String[] fileFormats = { FILE_FORMAT_TXT, FILE_FORMAT_JPEG, FILE_FORMAT_PNG };checkFile(file, fileFormats);} catch (FileException e) {e.printStackTrace();return e.getMessage();}//构建存储对象SysFile sysFile = SysFile.builder().name(getFilename(file.getOriginalFilename())).format(getFileFormat(file.getOriginalFilename())).data(file.getBytes()).size(file.getSize()).build();int i = fileMapper.insertFile(sysFile);return i > 0 ? "添加成功" : "添加失败";}private String getFileFormat(String filename) {int i = filename.lastIndexOf(".");return filename.substring(i + 1); //文件后缀}/*** 获取不带后缀的文件名*/private String getFilename(String originalFilename) {int i = originalFilename.lastIndexOf(".");return originalFilename.substring(0, i);}@GetMapping("downloadPage")public String downloadPage(ModelMap map) {List<SysFile> files = fileMapper.queryFiles();map.addAttribute("files", files);return "download";}@GetMapping("downloadFile/{id}")public void downloadFile(@PathVariable Integer id, HttpServletResponse response) throws IOException {SysFile sysFile = fileMapper.queryFileById(id);String filename = sysFile.getName() + "_" + System.currentTimeMillis() + "." + sysFile.getFormat();//指定下载文件名response.setHeader("Content-Disposition", "attachment; filename=" + filename);response.setCharacterEncoding("UTF-8");//告知浏览器文件大小response.addHeader("Content-Length", String.valueOf(sysFile.getSize()));//内容类型为通用类型,表示二进制数据流response.setContentType(getContentType(sysFile.getFormat()));InputStream is = new ByteArrayInputStream(sysFile.getData());OutputStream os = response.getOutputStream();byte[] buffer = new byte[1024];int l = 0;while ((l = is.read(buffer)) != -1) {os.write(buffer, 0, l);}is.close();os.close();}private String getContentType(String format) {switch (format) {case FILE_FORMAT_TXT:return MediaType.TEXT_PLAIN_VALUE;case FILE_FORMAT_JPEG:return MediaType.IMAGE_JPEG_VALUE;case FILE_FORMAT_PNG:return MediaType.IMAGE_PNG_VALUE;default:return MediaType.APPLICATION_OCTET_STREAM_VALUE; //通用类型}}}
效果图
成功下载 txt 文件。
成功下载 jpg 文件。
成功下载 png 文件。
项目结构图
相关文章:

【SpringBoot】19 文件/图片下载(MySQL + Thymeleaf)
Git仓库 https://gitee.com/Lin_DH/system 介绍 从 MySQL 中,下载保存的 blob 格式的文件。 代码实现 第一步:配置文件 application.yml spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8datasource:driver-class-name: com.mysql.…...

陪诊问诊APP开发实战:基于互联网医院系统源码的搭建详解
时下,开发一款功能全面、用户体验良好的陪诊问诊APP成为了医疗行业的一大热点。本文将结合互联网医院系统源码,详细解析陪诊问诊APP的开发过程,为开发者提供实用的开发方案与技术指导。 一、陪诊问诊APP的背景与功能需求 陪诊问诊APP核心目…...

Spark 中 RDD 的诞生:原理、操作与分区规则
Spark 的介绍与搭建:从理论到实践-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交:本地与集群模式全解析-CSDN博客 Spark on YARN:Spark集群模式之Yarn模式的原…...

c++构造与析构
构造函数特性 名称与类名相同:构造函数的名称必须与类名完全相同,并且不能有返回值类型(包括void)。 自动调用:构造函数在对象实例化时自动调用,不需要手动调用。 初始化成员变量:构造函数的主…...

C++(函数重载,引用,nullptr)
1.函数重载 C⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。传参时会自动匹配传入的参数,对应该函数的形参类型,进行函数调用,这样C函数调⽤就表现出了多态⾏为&a…...

django+postgresql
PostgreSQL概述 PostgreSQL 是一个功能强大的开源关系数据库管理系统(RDBMS),以其高度的稳定性、扩展性和社区支持而闻名。PostgreSQL 支持 SQL 标准并具有很多先进特性,如 ACID 合规、复杂查询、外键支持、事务处理、表分区、JS…...

前端滚动锚点(点击后页面滚动到指定位置)
三个常用方案:1.scrollintoView 把调用该方法的元素滚动到屏幕的指定位置,中间,底部,或者顶部 优点:方便,只需要获取元素然后调用 缺点:不好精确控制,只能让元素指定滚动到中间&…...

使用SSL加密465端口发送邮件
基于安全考虑,云虚拟主机的25端口默认封闭,如果您有发送邮件的需求,建议使用SSL加密端口(465端口)来对外发送邮件。本文通过提供.NET、PHP和ASP样例来介绍使用SSL加密端口发送邮件的方法,其他语言的实现思路…...

一些面试题总结(一)
1、string为什么是不可变的,有什么好处 原因: 1、因为String类下的value数组是用final修饰的,final保证了value一旦被初始化,就不可改变其引用。 2、此外,value数组的访问权限为 private,同时没有提供方…...

泄露的文档显示 Google 似乎意识到了 Tensor 处理器存在过热问题
Google 知道其 Tensor 芯片存在一些问题,尤其是在过热和电池寿命方面,显然他们正在努力通过即将推出的代号为"Malibu"的 Tensor G6 来解决这一问题。 Android Authority 泄露的幻灯片显示,过热是基于 Tensor 的 Pixel 手机退换货的…...

python爬虫案例——网页源码被加密,解密方法全过程
文章目录 1、任务目标2、网页分析3、代码编写1、任务目标 目标网站:https://jzsc.mohurd.gov.cn/data/company,该网站的网页源码被加密了,用于本文测验 要求:解密该网站的网页源码,请求网站并返回解密后的明文数据,网页内容如下: 2、网页分析 进入网站,打开开发者模式,…...

2.4_SSRF服务端请求伪造
SSRF服务端请求伪造 定义:服务端请求伪造。是一种攻击者构造请求后,交由服务端发起请求的漏洞; 产生原理:该服务器提供了从其他服务器获取数据的功能,但没有对用户提交的数据做严格校验; 利用条件&#…...

数据分析反馈:提升决策质量的关键指南
内容概要 在当今快节奏的商业环境中,数据分析与反馈已成为提升决策质量的重要工具。数据分析不仅能为企业提供全面的市场洞察,还能帮助管理层深入了解客户需求与行为模式。掌握数据收集的有效策略和工具,企业能够确保获得准确且相关的信息&a…...

一步步安装deeponet的详细教学
1.deepoent官网如下: https://github.com/lululxvi/deeponet 需要下载依赖 1.python3 2.DeepXDE(这里安装DeepXDE<0.11.2,这个最方便) Optional: For CNN, install Matlab and TensorFlow 1; for Seq2Seq, install PyTorch࿰…...

Devops业务价值流:版本发布最佳实践
敏捷开发中,版本由多个迭代构建而成,每个迭代都是产品进步的一环。当版本最后一个迭代完成时,便启动了至关重要的上线流程。版本发布流程与规划流程相辅相成,确保每个迭代在版本中有效循环执行,最终达成产品目标。 本…...

背包问题(三)
文章目录 一、二维费用的背包问题二、潜水员三、机器分配四、开心的金明五、有依赖的背包问题 一、二维费用的背包问题 题目链接 #include<iostream> #include<algorithm> using namespace std; const int M 110; int n,m,kg; int f[M][M];int main() {cin >…...

linux之调度管理(2)-调度器 如何触发运行
一、调度器是如何在程序稳定运行的情况下进行进程调度的 1.1 系统定时器 因为我们主要讲解的是调度器,而会涉及到一些系统定时器的知识,这里我们简单讲解一下内核中定时器是如何组织,又是如何通过通过定时器实现了调度器的间隔调度。首先我们…...

深入理解 Vue 3 中的 Props
深入理解 Vue 3 中的 Props Vue 3 引入了 Composition API 等新特性,组件的定义和使用也变得更为灵活。而在组件通信中,Props(属性)扮演了重要角色,帮助父组件向子组件传递数据,形成单向的数据流动&#x…...

校园周边美食探索及分享平台
摘要: 美食一直是与人们日常生活息息相关的产业。传统的电话订餐或者到店消费已经不能适应市场发展的需求。随着网络的迅速崛起,互联网日益成为提供信息的最佳俱渠道和逐步走向传统的流通领域,传统的美食业进而也面临着巨大的挑战࿰…...

内网对抗-信息收集篇SPN扫描DC定位角色区域定性服务探针安全防护凭据获取
知识点: 1、信息收集篇-网络架构-出网&角色&服务&成员 2、信息收集篇-安全防护-杀毒&防火墙&流量监控 3、信息收集篇-密码凭据-系统&工具&网站&网络域渗透的信息收集: 在攻防演练中,当完成边界突破后进入内…...

石墨舟氮气柜:半导体制造中的关键保护设备
石墨舟是由高纯度石墨材料制成的,主要用于承载硅片或其他基板材料通过高温处理过程,是制造半导体器件和太阳能电池片的关键设备之一。 石墨舟在空气中容易与氧气发生反应,尤其是在高温处理后,表面可能更为敏感;石墨舟具…...

性能调优专题(7)之Innodb底层原理与Mysql日志机制深入剖析
一、MYSQL的内部组件结构 大体来说,Mysql可以分为Server层和存储引擎层两部分。 1.1 Server层 Server层主要包括连接器、查询缓存、词法分析器、优化器等。涵盖MYSQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功…...

量子计算及其在密码学中的应用
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 量子计算及其在密码学中的应用 量子计算及其在密码学中的应用 量子计算及其在密码学中的应用 引言 量子计算概述 定义与原理 发展…...

LSM树 (Log-Structured Merge Tree)、Cuckoo Hashing详细解读
一、LSM 树 (Log-Structured Merge Tree) LSM 树(Log-Structured Merge Tree) 是一种专为 高效写入和批量更新 设计的数据结构,特别适合于 高写入密度 的应用场景,如数据库和文件系统。它广泛用于 NoSQL 数据库(如 Ca…...

VMware中的重要日志文件 vobd.log 学习总结
最近几天处理完毕存储的故障后,接着就是host方面的问题,Vmware无法访问到存储,其实存储的LUN和POOL 已经online ready了,但是主机还是访问不到存储。 这里介绍下Vmware中的一个重要的日志文件 vobd.log,该文件对于分析…...

MyBatis 返回 Map 或 List<Map>时,时间类型数据,默认为LocalDateTime,响应给前端默认含有‘T‘字符
一、问题 MyBatis 返回 Map 或 List时,时间类型数据,默认为LocalDateTime Springboot 响应给前端的LocalDateTime,默认含有’T’字符,如何统一配置去掉 二、解决方案 1、pom.xml 增加依赖(2024.11.6 补充ÿ…...

ASR TP
ASR翱捷科技 ASR kernel 5.10 android14 ASR EVB平台 jd9365tr(jadard) spi 1.驱动: 跟mtk驱动一样,放进去,不用改 asr_android14.0_alpha\asr\kernel\linux\drivers\input\touchscreen\jadard makefile: asr_android14.0_alpha\asr\kernel\linux\drivers\input\t…...

Tomcat与Nginx之全面比较
概况 Apache Tomcat Apache Tomcat,通常简称为Tomcat,是一个开源的Web应用服务器,它主要用于运行Java Web应用程序。Tomcat实现了Java Servlet和JavaServer Pages(JSP)技术,这些是Java EE规范的一部分。To…...

这是一个bug求助帖子--安装kali 遇坑
第一个报错 介质:kali-linux-2024.1-live-amd64 环境:Dell笔记本 i510代cpu 现象及操作 安装完以后 然后我换了个国内的源进行了以下操作 apt-get update:更新源列表 apt-get upgrade:更新所有可以更新的软件包 然后进行清理。…...

IntelliJ Idea设置自定义快捷键
我IDEA的快捷键是自己修改成了和Eclipse相似,然后想要跳转到某个方法的上层抽象方法没有对应的快捷键,IDEA默认的是Ctrl U (Windows/Linux 系统) 或 Command U (Mac 系统),但是我的不起作用&a…...