1. 简介

本篇文章介绍了如何将SpringBoot和Mybatis-plus整合,实现文件下载的可选模式。用户可以上传Pdf、Word、Excel等类型的文件到数据库,然后在前端进行选择并下载。

本文中,我们将使用Vue作为前端框架,使用组件合并进行接口调用,实现相关功能。

2. 技术栈

  • SpringBoot 2.5.0
  • Mybatis-plus 3.4.2
  • Vue 2.6.12

3. 实现步骤

3.1 创建数据库

首先,需要创建一个数据库用于存储文件数据。假设我们使用的数据库名为file_db,其中数据表名为file_info

CREATE TABLE `file_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `file_name` varchar(255) NOT NULL COMMENT '文件名',
  `file_type` varchar(50) NOT NULL COMMENT '文件类型',
  `file_data` longblob NOT NULL COMMENT '文件数据',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.2 引入依赖

在SpringBoot的pom.xml文件中加入Mybatis-plus和MySQL等必要依赖:

<!-- Mybatis-plus依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

<!-- MySQL驱动依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

3.3 配置数据源和Mybatis-plus

application.yml配置文件中,添加数据源和Mybatis-plus的相关配置:

# 数据源配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/file_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
    username: root
    password: admin
    driver-class-name: com.mysql.cj.jdbc.Driver

# Mybatis-plus配置
mybatis-plus:
  configuration:
    use-generated-keys: true
    map-underscore-to-camel-case: true
  mapper-locations: classpath*:mapper/*.xml
  global-config:
    db-config:
      id-type: auto
      insert-strategy: not_null
      update-strategy: not_null
      delete-strategy: not_null
      select-strategy: not_null

其中,urlusernamepassword分别指定要连接的数据库,driver-class-name是MySQL的驱动类。

3.4 创建实体和Mapper

接下来,在项目中创建一个实体类FileInfo和一个Mapper接口FileInfoMapper,实现数据库中的文件数据的映射和操作。

  • FileInfo实体类包含文件名、文件类型和文件数据等属性。
  • FileInfoMapper接口继承Mybatis-plus的BaseMapper接口,并加上@Mapper注解,用于对FileInfo实体类进行操作。
@Data
public class FileInfo {
    private Integer id;

    private String fileName;

    private String fileType;

    private byte[] fileData;
}

@Mapper
public interface FileInfoMapper extends BaseMapper<FileInfo> {
}

3.5 编写上传和下载接口

FileController类中编写文件上传和下载的接口,其中,文件上传接口包括文件的读取和保存到数据库中的操作;文件下载接口则是从数据库中获取文件数据,并以流的形式将文件输出,提供下载服务。

@RestController
@RequestMapping("/file")
public class FileController {

    @Autowired
    private FileInfoMapper fileInfoMapper;

    // 文件上传接口
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws IOException {
        FileInfo fileInfo = new FileInfo();

        // 文件名
        String fileName = file.getOriginalFilename();
        fileInfo.setFileName(fileName.substring(0, fileName.lastIndexOf(".")));

        // 文件类型
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
        fileInfo.setFileType(fileType);

        // 文件数据
        fileInfo.setFileData(file.getBytes());

        // 保存到数据库
        fileInfoMapper.insert(fileInfo);
        return "文件上传成功";
    }

    // 文件下载接口
    @GetMapping("/download/{id}")
    public void download(@PathVariable("id") Integer id, HttpServletResponse response) throws IOException {
        FileInfo fileInfo = fileInfoMapper.selectById(id);
        String fileName = fileInfo.getFileName() + "." + fileInfo.getFileType();

        // 设置Http响应头,告诉浏览器以下载的方式打开文件
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        // 写出文件流
        response.getOutputStream().write(fileInfo.getFileData());
    }
}

3.6 实现前端组件

最后,我们使用Vue实现前端界面,并实现相应的组件,提供用户选择和下载文件的功能。

  • 在Vue项目中,创建FileUpload组件,用于实现文件的上传和保存。
<template>
  <div>
    <input type="file" @change="handleUpload" />
    <h3>{{fileName}}</h3>
  </div>
</template>

<script>
export default {
  data() {
    return {
      file: null,
      fileName: "",
    };
  },
  methods: {
    handleUpload(e) {
      this.file = e.target.files[0];
      this.fileName = this.file.name;
    },
    async upload() {
      if (!this.file) {
        return;
      }
      const formData = new FormData();
      formData.append("file", this.file);
      await this.$axios.post("/file/upload", formData);
      this.fileName = "";
    },
  },
};
</script>
  • 创建FileDownload组件,用于实现文件的下载和选择。
<template>
  <div>
    <ul>
      <li v-for="file in files" :key="file.id" @click="download(file.id)">
        {{ file.fileName }}.{{ file.fileType }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      files: [],
    };
  },
  async created() {
    const { data } = await this.$axios.get("/file/all");
    this.files = data;
  },
  methods: {
    async download(id) {
      await this.$axios.get(`/file/download/${id}`, { responseType: "blob" }).then((response) => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement("a");
        link.href = url;
        link.setAttribute("download", "file");
        document.body.appendChild(link);
        link.click();
      });
    },
  },
};
</script>

3.7 编写文件查询接口

最后,我们需要实现一个文件获取所有文件的接口,以方便在前端展示所有已上传的文件。我们添加以下接口在FileController中:

@GetMapping("/all")
public List<FileInfo> getAll() {
    return fileInfoMapper.selectList(null);
}

4. 总结

本文介绍了如何使用SpringBoot和Mybatis-plus,实现文件下载的可选模式,并在前端中使用Vue进行组件合并和接口调用,提供给用户多种文件格式的下载选项。在实现过程中,我们学习了如何将文件数据保存到数据库中,以及如何从数据库中读取文件数据并提供下载服务。