如何使用 MySQL、Thymeleaf 和 Spring Boot 从数据库上传和下载多个文件

news2024/11/18 19:48:58

使用百里香叶的春季启动上传和下载示例。在本文中,我们将学习如何从数据库上传和下载文件。

上传和下载文件是任何应用程序的重要组成部分之一。众所周知,我们使用 Spring Boot 使开发过程变得简单。因此,在这里我们将创建一个示例来从数据库上传和下载文件。我们将在视图层使用百里香叶模板。Spring Data JPA 将在数据访问层使用。这里的关系数据库是MYSQL。

使用百里香叶的春季启动上传和下载文件示例

在此示例中,我们将创建一个视图,在其中查看如何上传和下载文件。

第 1 步:打开 IDE STS-弹簧工具套件

第 2 步:转到 Spring 入门项目>文件。

步骤3: 现在,填写如下所示的所有字段,然后单击下一步。

步骤4: 现在,添加百里香叶,春季数据JPA,龙目岛和春季网络的依赖项,然后单击下一步>完成。

现在,等待一段时间,您的项目结构将准备就绪。转到pom.xml文件,您将看到将自动添加以下依赖项

<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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>upload.download</groupId>
    <artifactId>springboot-thymeleaf-mysql-upload-download-files</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-thymeleaf-mysql-upload-download-files</name>
    <url>http://localhost:8080</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.4.0-b180830.0359</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

在 MYSQL 中创建数据库

mysql> create database updownload;

配置应用程序。属性文件

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/updownload?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root

#Multipart
spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=2KB
spring.servlet.multipart.max-file-size=200MB
spring.servlet.multipart.max-request-size=215MB
  • spring.jpa.hibernate.ddl-auto设置为更新,以便我们将要进行的任何更改都将反映在架构中。
  • spring.datasource.url 用于设置 MYSQL DB 的 URL
  • spring.datasource.username 用于设置 username 和 spring。 datasource. password用于设置密码。
  • spring.datasource.driver-class-name 用于设置驱动程序类名。
  • spring.jpa.show-sql 设置为 true 以显示 Hibernate 生成的 SQL。
  • spring.jpa.properties.hibernate.dialect 用于为所选数据库生成更好的 SQL。
  • spring.jpa.properties.hibernate.format_sql设置为 true 以格式化 SQL 查询。
  • server.port 设置为 8888
  • spring.servlet.multipart.enabled 设置为 true 以提供对 multipart 的支持。
  • spring.servlet.multipart.file-size-threshold用于设置文件的最大大小。在阈值大小之后,文件将被写入光盘。
  • spring.servlet.multipart.max-file-size 表示最大文件大小
  • spring.servlet.multipart.max-request-size 表示总请求大小。

创建模型类

FileEntity .java

package upload.download.entity;

import javax.persistence.*;

@Entity
@Table(name = "file_table")
public class FileEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "file_id")
    private Long fileId;

    @Column(name = "file_name")
    private String fileName;

    @Column(name = "file_type")
    private String fileType;
    @Lob
    @Column(name = "file_byte")
    private byte[] fileByte;

    public FileEntity() {
    }

    public FileEntity(String fileName, String fileType, byte[] fileByte) {
        this.fileName = fileName;
        this.fileType = fileType;
        this.fileByte = fileByte;
    }

    public Long getId() {
        return fileId;
    }

    public void setId(Long id) {
        this.fileId = id;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileType() {
        return fileType;
    }

    public void setFileType(String fileType) {
        this.fileType = fileType;
    }

    public byte[] getFileByte() {
        return fileByte;
    }

    public void setFileByte(byte[] fileByte) {
        this.fileByte = fileByte;
    }
}

FileInfo.java

package upload.download.entity;

public class FileInfo {

    private String fileInfoName;
    private String fileURL;

    public FileInfo() {
    }

    public FileInfo(String fileInfoName, String fileURL) {
        this.fileInfoName = fileInfoName;
        this.fileURL = fileURL;
    }

    public String getFileInfoName() {
        return fileInfoName;
    }

    public void setFileInfoName(String fileInfoName) {
        this.fileInfoName = fileInfoName;
    }

    public String getFileURL() {
        return fileURL;
    }

    public void setFileURL(String fileURL) {
        this.fileURL = fileURL;
    }
}
  • @Entity用于批注类以指示它们是 JPA 实体。
  • @Table批注用于指定应与实体映射的表的名称。
  • @Id注释用于主键。
  • 我使用龙目岛库删除了样板代码。如果您想知道什么是龙目岛,请查看这篇文章 https://codedec.com/tutorials/how-to-configure-lombok-into-eclipse/

在数据库中,它将像这样显示

 

现在,使用 MYSQL 工作台将 TinyBLOB 数据类型更改为LongBlob。

创建存储库接口

这里的存储库是 DAO 层,它执行所有数据库操作。创建 FileEntityRepository 接口,该接口将扩展 JPARepository<ClassName, ID>。

package upload.download.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.stereotype.Repository;
import upload.download.entity.FileEntity;

@Repository
@EnableJpaRepositories
public interface FileEntityRepository extends JpaRepository<FileEntity, Long> {
    FileEntity findByFileName(String fileName);
}

创建控制器类

对网页的请求将由控制器类中的处理程序方法使用 @GetMapping 处理。

package upload.download.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import upload.download.entity.FileEntity;
import upload.download.repository.FileEntityRepository;

import java.util.ArrayList;
import java.util.List;

@Controller
public class UploadController {

    @Autowired
    private FileEntityRepository fileEntityRepository;


    /**
     * Get index page
     *
     * @return index
     */

    @GetMapping("/")
    public String getIndexFilePage() {
        return "index";
    }

    @PostMapping("/")
    public String uploadFiles(@RequestParam("files") MultipartFile[] multipartFiles, Model model) {
        List<String> listFileNames = new ArrayList<>();

        try {
            List<FileEntity> storeFiles = new ArrayList<>();

            for (MultipartFile file : multipartFiles) {
                FileEntity fileEntity = fileEntityRepository.findByFileName(file.getOriginalFilename());

                if (fileEntity != null) {
                    fileEntity.setFileByte(file.getBytes());
                } else {
                    fileEntity = new FileEntity(file.getOriginalFilename(), file.getContentType(), file.getBytes());
                }
                listFileNames.add(file.getOriginalFilename());
                storeFiles.add(fileEntity);
            }

            // save all files
            fileEntityRepository.saveAll(storeFiles);

            // successfully message after uploaded
            model.addAttribute("message", "Files uploaded successfully!");
            model.addAttribute("files", listFileNames);
        } catch (Exception e) {
            // fail message for unsupported file or max size
            model.addAttribute("message", "Fail");
            model.addAttribute("files", listFileNames);
        }
        return "index";
    }
}
package upload.download.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import upload.download.entity.FileEntity;
import upload.download.entity.FileInfo;
import upload.download.repository.FileEntityRepository;

import java.util.List;
import java.util.stream.Collectors;

@Controller
public class DownloadController {

    @Autowired
    private FileEntityRepository fileEntityRepository;

    /**
     * Get and display file stored in the database.
     *
     * @return download-file page
     */

    @GetMapping("/download/files")
    public String getListOfFiles(Model model) {
        List<FileInfo> fileInfoList = fileEntityRepository.findAll()
                .stream()
                .map(fileEntity -> {
                            String fileInfoName = fileEntity.getFileName();
                            String fileURL = MvcUriComponentsBuilder
                                    .fromMethodName(
                                            DownloadController.class,
                                            "downloadFile",
                                            fileEntity.getFileName())
                                    .build()
                                    .toString();
                            return new FileInfo(fileInfoName, fileURL);
                        }
                ).collect(Collectors.toList());


        model.addAttribute("files", fileInfoList);
        return "download-file";
    }

    /**
     * Get file to download.
     *
     * @return file from database to be downloaded
     */

    @GetMapping("/download/files/{fileInfoName}")
    public ResponseEntity<byte[]> downloadFile(@PathVariable String fileInfoName) {
        FileEntity downloadFileEntity = fileEntityRepository.findByFileName(fileInfoName);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + downloadFileEntity.getFileName() + "\"")
                .body(downloadFileEntity.getFileByte());
    }
}

@Controller注释将学生控制器类标记为请求处理程序。现在让我们打破上面的代码并理解它。

使用百里香叶创建视图

转到 src/main/resources/template 文件夹并创建一个 index.html 文件。现在在寄存器中.html文件确保添加以下代码:

要了解如何迭代百里香叶中的对象列表,请查看这篇文章 使用 Spring 引导在百里香叶中迭代列表

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Spring Boot - Thymeleaf - MySQL| Upload -- Download -- Files</title>
    <link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
<div id="wrapper">
    <div id="navigator">
        <!-- Navigator -->
        <nav>
            <div class="navbar">
                <div class="navbar-banner"><a class="white" href="/"><img src="" alt="Logo"></a></div>
                <div class="nav-links"></div>
            </div>
        </nav>
    </div>
    <div class="upload-download-card">
        <h2 style="text-align: center">Spring Thymeleaf MySQL |
            <a class="button-style-1" href="/">Upload</a>
            <a class="button-style-1" href="/download/files">Download</a>
        </h2>
        <hr style="width: 90%; height: 2px; background-color: black;">
        <div>
            <form method="POST" enctype="multipart/form-data" id="fileUploadForm">
                <h3 style="text-align: center">Upload One Or Multiple Files</h3>
                <div id="upload-group">
                    <label for="files">Upload Files:</label>
                    <input type="file" id="files" placeholder="Upload Multiple Files" name="files" multiple>
                    <button type="submit" class="button-style-1" id="btnSubmit">Upload</button>
                </div>
            </form>
            <div>
                <!-- Message Success|Fail-->
                <div class="message-card" th:if="${message}">
                    <strong><span th:text="${message}"/></strong>
                    <hr>
                    <ul th:each="filename: ${files}">
                        <li><span th:text="${filename}"/></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>
<footer id="footer">
    <div id="footer-content">
        <p>Copyright ©2022 All rights reserved |</p>
        <p title="Popa Catalin">&nbsp;Popa Catalin</p>
    </div>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Spring Boot - Thymeleaf - MySQL| Upload -- Download -- Files</title>
    <link rel="stylesheet" type="text/css" href="/css/style.css">
    <link rel="stylesheet" type="text/css" href="/css/table.css">
</head>
<body>
<div id="wrapper">
    <div id="navigator">
        <!-- Navigator -->
        <nav>
            <div class="navbar">
                <div class="navbar-banner"><a class="white" href="/"><img src="" alt="Logo"></a></div>
                <div class="nav-links"></div>
            </div>
        </nav>
    </div>
    <div class="upload-download-card">
        <h2 style="text-align: center">Spring Thymeleaf MySQL |
            <a class="button-style-1" href="/">Upload</a>
            <a class="button-style-1" href="/download/files">Download</a>
        </h2>
        <hr style="width: 90%; height: 2px; background-color: black;">
        <div class="download-group">
            <h2 style="text-align: center">Uploaded Files</h2>
            <div class="table-container">
                <table class="customTable">
                    <thead>
                    <tr>
                        <th>No</th>
                        <th>Filename</th>
                        <th>Download</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr th:each="files, rowStat: ${files}">
                    <tr th:each="file, rowStat: ${files}">
                        <td th:text="${rowStat.count}">1</td>
                        <td th:text="${file.fileInfoName}">File-Name</td>
                        <td><a class="download-button" th:href="${file.fileURL}">Link</a></td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>
<footer id="footer">
    <div id="footer-content">
        <p>Copyright ©2022 All rights reserved |</p>
        <p title="Popa Catalin">&nbsp;Popa Catalin</p>
    </div>
</footer>
</body>
</html>

现在,运行 UploadAndDownloadApplication 并转到 localhost:8888 并查看以下输出。

 

 

 

通过这种方式,我们学会了如何从/向数据库上传、下载文件。

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

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

相关文章

高通Ride开发包使用指南(1)

高通Ride开发包使用指南&#xff08;1&#xff09;1引言1.1目的1.2范围1.3术语2系统前提条件和设置2.1先决条件2.1.1硬件2.1.2 软件2.1.3其他所需软件&#xff1a;2.2布线和设置1引言 1.1目的 本文档面向高通公司Snapdragon Ride的用户™ 平台3.0&#xff08;Cetus&#xff0…

点击化学DBCO-PEG8-Benzylamine,二苯并环辛炔-PEG8-苄胺标记试剂

【中文名称】二苯并环辛炔-八聚乙二醇-苄胺 【英文名称】 DBCO-PEG8-Benzylamine 【CAS号】N/A 【分子式】C42H55N3O10 【分子量】761.91 【基团】DBCO基团 【纯度】95%(HPLC) 【规格标准】1g&#xff0c;5g&#xff0c;10g&#xff0c;包装灵活&#xff0c;可进行相应的封装。…

[附源码]JAVA毕业设计微留学学生管理系统(系统+LW)

[附源码]JAVA毕业设计微留学学生管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技…

【2022.12.08】备战春招Day3——每日一题 + 406. 根据身高重建队列

【每日一题】1812. 判断国际象棋棋盘中一个格子的颜色 题目描述 给你一个坐标 coordinates &#xff0c;它是一个字符串&#xff0c;表示国际象棋棋盘中一个格子的坐标。下图是国际象棋棋盘示意图。 如果所给格子的颜色是白色&#xff0c;请你返回 true&#xff0c;如果是黑色…

DataX 源码调试及打包

文章目录1、源码分析2、打包3、任务测试4、job配置详解Reader&#xff08;读插件&#xff09;Writer&#xff08;写插件&#xff09;通用配置前文回顾&#xff1a; 《DataX 及 DataX-Web 安装使用详解》 除了前文介绍的我们可以直接安装使用外&#xff0c;还可以下载源码打包&…

一文解决Kubernetes 的 API 流量查看器 - Kubeshark

一、Kubeshark 是什么&#xff1f; Kubeshark 由 2021 年 UP9 公司开源的 K8s API 流量查看器 Mizu 发展而来&#xff0c;试图成为一款 K8s 全过程流量监控工具。 Kubeshark 被叫做 kubernetes 的 API 流量查看器&#xff0c;它提供对进出 Kubernetes 集群内容器和 pod 的所有…

[附源码]JAVA毕业设计微服务的高校二手交易平台(系统+LW)

[附源码]JAVA毕业设计微服务的高校二手交易平台&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 …

多线程与高并发(14)——Executor框架(线程池基础)

一、简介 线程是什么&#xff0c;线程是一个任务的工作单元和执行单元。我们在用线程的时候知道&#xff0c;要创建线程&#xff0c;再执行线程。如果任务多的情况呢&#xff0c;会有大量的创建销毁线程的资源消耗&#xff0c;这时候就引入了线程池的概念。 JDK5开始&#xff…

使用Maven创建Servlet项目

创建Maven项目 点击FIle, 选择new ,选择Project… 选择Maven 然后点击next. 选择自己想要创建项目的目录.点击next 引入依赖 在pom.xml中添加servlet依赖. 先书写dependencies标签.然后在 Maven中央仓库 中找到servlet的依赖.复制填写进去. 这里是我常用的一个 Maven中央仓库…

TI Lab_SRR学习_3 速度扩展_2 interChirpProcessing_RangeDPU

RangeProcDSP共分为三步,如下图所示 transfers ADCBuf data through dataIn EDMA channels in ping/pong alternate order to FFT input scratch buffer - adcDataIn.Range FFT processing is done by using DSPlib and mmwavelib APIs. FFT input data is stored in input sc…

[附源码]计算机毕业设计JAVA中青年健康管理监测系统

[附源码]计算机毕业设计JAVA中青年健康管理监测系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM …

Python 实战分析某招聘网站数据分析岗位的招聘情况

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~ 今天案例难度指数: ☆☆☆ 准备 环境使用&#xff1a; Anaconda (python3.9) –>识别我们写的代码 开发工具&#xff1a; jupyter notebook –>代码编辑功能敲代码的工具 相关模块&#xff1a; seaborn pandas …

在CentOS7.9系统上安装N卡3060驱动、CUDA和离线升级gcc(4.8—>8.3)用以编译框架的过程记录

1、更换yum源 主要是在终端操作需要&#xff0c;在显示器界面可以直接联网解决网络问题进行软件安装或更新 """"备份原来的源""" mv /etc/yum.repos.d/ /etc/yum.repos.d.bak/ mkdir /etc/yum.repos.d vim /etc/yum.repos.d/xxx.repo &qu…

LeetCode HOT 100 —— 155.最小栈

题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop() 删除堆栈顶部的元素。 int top() 获取堆栈顶部的元素。 …

JavaScript 删除对象中的某一项

delete let obj{a:1,b:2,c:3,d:4,e:5,f:6} delete obj.b console.log(obj)运行结果&#xff1a; Reflect.deleteProperty JavaScript 中的静态方法 Reflect.deleteProperty() 允许用于删除对象上的属性。它很像 deleteoperator&#xff0c;但它是一个函数。 Reflect.delet…

Python操作Azure Blob Storage

安装 Azure Storage SDK for Python 最简单的方式是在安装了 python 和 pip 的机器上直接执行下面的命令&#xff1a; pip install azure-storage 安装完成后通过 pip freeze 命令查看安装的版本&#xff1a; 由于 Azure Storage SDK for Python 是一个开源项目&#xff0c;…

Buildroot系列开发(七)block device

摘自&#xff1a;百问网 文章目录1.块设备2.1 什么是块设备&#xff1f;raw flash&#xff1f;2.2 block device 列表2.3 块设备分区2.4 传输数据到块设备2. 块设备文件系统2.1 支持的块设备文件系统2.2 linux / unix 其他日志文件系统2.3 F2FS2.4 SquashFS2.5 如何选择最佳文件…

计算机网络-转发表和路由选择协议

有志者&#xff0c;事竟成 文章目录一、描述1、转发表和路由选择协议二、总结一、描述 1、转发表和路由选择协议 前面我们说过&#xff0c;路由器从与它相连的一条通信链路得到分组&#xff0c;然后向与它相连的另一条通信链路转发该分组。但是路由器怎样决定它应当向哪条链路…

Docker[4]-Docker数据卷

数据卷 前面我们介绍了镜像和容器&#xff0c;通过镜像我们可以启动多个容器&#xff0c;但是我们发现当我们的容器停止获取删除后&#xff0c;我们在容器中的应用的一些数据也丢失了&#xff0c;这时为了解决容器的数据持久化&#xff0c;我们需要通过容器数据卷来解决这个问…

一文4000字教你如何使用可视化的Docker进行UI自动化测试

随着 docker 的发展&#xff0c;很多测试的同学也已经在测试工作上使用 dockr 作为环境基础去进行一些自动化测试&#xff0c;这篇文章主要讲述我们在 docker 中使用浏览器进行自动化测试如果可以实现可视化&#xff0c;同时可以对浏览器进行相关的操作。 开篇 首先我们先了解…