自学内容网 自学内容网

一文搞懂springboot上传+下载文件的总体逻辑

Springboot+文件上传下载问题

需要hutool的工具 hutool可以生成数据md5等一些工具 非常好用

依赖

  <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.3</version>
        </dependency>

如过想传输比较大的数据还需要我们配置相应的依赖

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

文件传输的总体逻辑

首先我们需要一个测试工具postman 上传文件给服务端(springboot) 具体大家可以搜一下如何使用

我们的数据都是存储在服务器磁盘上的。当我们把数据存储到服务器的磁盘上就完成了上传文件的过程。

再从服务器的磁盘上下载文件就完成了下载过程。

我们下载文件的过程中 需要获取文件在服务器的名字 等信息 来定位文件在服务器中的位置。

所以我们需要数据库(Mysql)来在逻辑上 存储文件的一些信息。拿到文件的逻辑信息(下载链接后)

就可以通过请求接口 来通过网络流传输到自己的本地。

数据库

在这里插入图片描述

大概需要这样的一些信息 来逻辑存储文件的一些属性。

当然后台也需要有controller entity mapper service等 这些是基础 我就不一一展示

上传文件

在Yml简单定义一下下载的地址:

files:
  upload:
    path: D:/learnjava/MyAitest/files/

在这里使用该地址

  @Value("${files.upload.path}")
    private String fileuploadPath;

upload 代码的总体逻辑就是

1.我们从本地上传文件 服务器(springboot)获取到

原始的文件名(我们本地的文件名)获取文件类型(后缀 例如.txt) 获取文件的大小 这些都需要后面存储到数据库保留数据信息

这些使用一些FileUtil工具可以实现

2.判断目录是否存在 如果不存在则创建这个目录

使用IdUtil随机生成文件名

再加上原来文件的后缀形成最终我们需要存储到服务器的位置

 File uploadFile= new File(fileuploadPath+uuid+ StrUtil.DOT+type);//最终存储的位置

然后存储到磁盘

3.另外每个文件内容转换成md5后 都是唯一的。利用这个特性

我们获取到当前上传文件的md5 然后再在数据库中查找是否存在这个md5如果已经存在 那么该文件的下载地址就和它相同md5的那个文件的下载地址是一样的 并且删除掉这个文件不让它存在磁盘

这样可以避免磁盘空间的浪费

String md5= SecureUtil.md5(uploadFile);//工具获取起md5
        Files dbFiles=getFileByMd5(md5);
        if(dbFiles!=null){
            url=dbFiles.getUrl();
            uploadFile.delete();


        }
        else{
            url="http://localhost:9090/file/"+fileuuid;//上传成功返回属性
        }

4.最后把文件信息保存在数据库

总结一下:每次上传一个文件 数据库多一条数据 但是磁盘不一定多一条数据 有可能会删除

下载文件

1.有刚才的fileuploadPath+接口请求传来的文件名+后缀

定位到需要下载的文件

 @GetMapping("/{fileUUID}")
 File loadFile = new File(fileuploadPath+fileUUID);//把文件获取到

2.需要我们设置返回的header 和contentType

  response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileUUID,"UTF-8"));

3.把文件转换成字节流

通过HTTP的setvletoutstream通道 把数据输出回去 就完成了下载操作

 ServletOutputStream out=response.getOutputStream();//获取返回数据的通道 写数据
byte[] bytes = FileUtil.readBytes(loadFile);//把文件拆解成 字节- 字节的形式
        out.write(bytes);//写出数据

        //对网络传输头 内容  流 文件进行处理

        out.flush();//刷新
        out.close();//关闭

上传和下载的全部controller代码

package com.hxt.myaitest.controller;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hxt.myaitest.entity.Files;
import com.hxt.myaitest.service.IFileService;
import org.apache.xmlbeans.impl.xb.ltgfmt.TestCase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URLEncoder;

/**
 *
 *
 * 文件上传接口
 */

@RestController
@RequestMapping("/file")
public class FileController {
    @Autowired
    private IFileService fileService;

    @Value("${files.upload.path}")
    private String fileuploadPath;

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws Exception {
        String originalFilename = file.getOriginalFilename();//获取文件的名字
        String type= FileUtil.extName(originalFilename);//获取文件的类型//后缀
        long size=file.getSize();//获取文件的大小
        //先存储到磁盘
        //再存储到数据库
        File uploadParentFile = new File(fileuploadPath);//原始目录的地址
        if (!uploadParentFile.exists()) {
            uploadParentFile.mkdirs();
        }//需要存在否则创建一个目录
        String uuid= IdUtil.fastSimpleUUID();//随机生成文件名标识
        String fileuuid=uuid+StrUtil.DOT+type;//文件名+后缀(类型) 形成最后的UUID
        File uploadFile= new File(fileuploadPath+uuid+ StrUtil.DOT+type);//最终存储的位置
        //存储磁盘
        file.transferTo(uploadFile);//存储磁盘
String url;
        //保证重复的文件不会都读到磁盘里面占用空间
        String md5= SecureUtil.md5(uploadFile);//工具获取起md5
        Files dbFiles=getFileByMd5(md5);
        if(dbFiles!=null){
            url=dbFiles.getUrl();
            uploadFile.delete();


        }
        else{
            url="http://localhost:9090/file/"+fileuuid;//上传成功返回属性
        }









        //把重要信息 文件名字  类型和大小存储到数据库
        Files savefile=new Files();//java里面的实体file 而不是自带的文件系统
        savefile.setMd5(md5);
        savefile.setName(originalFilename);
        savefile.setType(type);
        savefile.setSize(size/1024);//把B转换成KB
        savefile.setUrl(url);
        fileService.save(savefile);//保存到数据库
        return url;
    }

    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws Exception {
        File loadFile = new File(fileuploadPath+fileUUID);//把文件获取到

        //对网络传输头 内容  流 文件进行处理

        ServletOutputStream out=response.getOutputStream();//获取返回数据的通道 写数据
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileUUID,"UTF-8"));
        byte[] bytes = FileUtil.readBytes(loadFile);//把文件拆解成 字节- 字节的形式
        out.write(bytes);//写出数据

        //对网络传输头 内容  流 文件进行处理

        out.flush();//刷新
        out.close();//关闭



    }

    private Files getFileByMd5(String md5) {
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        return fileService.getBaseMapper().selectOne(queryWrapper);
    }

}

原文地址:https://blog.csdn.net/qq_53539629/article/details/143061411

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!