Spring Boot 3 文件管理:上传、下载、预览、查询与删除(全网最全面教程)

news2024/11/23 23:57:44

      在现代Web应用中,文件管理是一个非常重要的功能。Spring Boot作为Java开发领域的热门框架,提供了丰富的工具和API来简化文件管理的操作。本文将详细介绍如何使用Spring Boot 3进行文件的上传、下载、预览、查询与删除操作,并提供一个完整的示例代码。

文件预览支持多格式!!!(文档/图片/视频/音频.....)

 废话不多说,直接开撸。

                                                                  

1.pom.xml 和 yml

        <!--File 文件Util-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.20</version>
        </dependency>

     <!--StringUtils-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
# 自定义信息
customInfo:
  # 获取文件存放信息路径
  file:
    storagePath: "/static/file/"

2.Util 工具类

public class ToolUtil {
    /**
     * 判断权限是否存在
     */
    public static Boolean bollPurviewTool(String[] list, String str){
        String[] list2 = str.split(",");
        for (String item:list) {
            for (String item2:list2) {
                if (item.equals(item2)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取当前系统路径的上一级
     */
    public static String currentParentPath(){
        String currentDirectory = System.getProperty("user.dir");
        File file = new File(currentDirectory);
        String parentDirectory = file.getParent();
        return  parentDirectory;
    }



}

3.FileController

备注:@RateLimit  @VerifySign 注解是我的自定义注解你可以删除, 

         JwtRedistService  是我的权限判定方法,你可以删除

         JwtInfo  是我的token令牌涉及相关方法 ,这些方法你都可以去掉

import com.portalwebsiteservice.demos.web.Dto.JwtInfo;
import com.portalwebsiteservice.demos.web.Dto.Result;
import com.portalwebsiteservice.demos.web.Enum.PurviewEnum;
import com.portalwebsiteservice.demos.web.Enum.ResultEnum;
import com.portalwebsiteservice.demos.web.Service.FileService;
import com.portalwebsiteservice.demos.web.Service.JwtRedistService;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

import static com.portalwebsiteservice.demos.web.Util.ToolUtil.bollPurviewTool;


/**
 * 文件管理
 */
@RestController
@RequestMapping("/file")
public class FileController {

    @Resource
    private FileService fileService;

    @Resource
    private JwtRedistService jwtRedistService;

    /**
     * 文件上传
     */
    @PostMapping("/upload")
    public Result uploadFile(@RequestParam("file") MultipartFile file) {
        Result result = new Result();
        if (file==null) {
            result.setCode(400);
            result.setMsg("至少选择一个文件上传!");
            return result;
        }else {
            return fileService.uploadFileService(file);
        }

    }

    /**
     * 文件下载
     */
    @RateLimit
    @GetMapping("/download/{id}")
    public ResponseEntity<FileSystemResource> downloadFile(@PathVariable String id,@RequestHeader("Authorization") String token) {
            JwtInfo jwtInfo = jwtRedistService.getUserInfo(token);
            return fileService.downloadFileService(jwtInfo,id);
    }
    /**
     * 文件预览
     */
    @RateLimit
    @GetMapping("/visit/{path}")
    public void downloadFile(@PathVariable String path, HttpServletResponse response) {
        fileService.viewFile(path,response);
    }


    /**
     * 文件查询 (管理端)
     */
    @RateLimit
    @VerifySign
    @GetMapping("/queryAll")
    public Result queryFileAll(@RequestParam Integer page,@RequestParam Integer limit, @RequestParam(required = false) String keyword, @RequestHeader("Authorization") String token){
        Result result = new Result();
        try {
            JwtInfo jwtInfo = jwtRedistService.getUserInfo(token);
            //需要超级管理员
            if (bollPurviewTool(jwtInfo.getPurview(), PurviewEnum.ADMINISTRATOR.getValue())){
                return fileService.queryAllFileService(jwtInfo,keyword,page,limit);
            }else {
                result.setCode(ResultEnum.ADMIN.getCode());
                result.setMsg(ResultEnum.ADMIN.getData());
            }
        }catch (Exception e){
            result.setCode(ResultEnum.UNKNOWNERROR.getCode());
            result.setMsg(ResultEnum.FORBIDDEN.getData());
            result.setData(e.getCause());
        }
        return result;
    }

    /**
     * 文件查询 (服务端)
     */
    @RateLimit
    @GetMapping("/query")
    public Result queryFile(@RequestParam String id, @RequestHeader("Authorization") String token){
        Result result = new Result();
        try {
            JwtInfo jwtInfo = jwtRedistService.getUserInfo(token);
            return fileService.queryFileService(jwtInfo,id);
        }catch (Exception e){
            result.setCode(ResultEnum.UNKNOWNERROR.getCode());
            result.setMsg(ResultEnum.FORBIDDEN.getData());
            result.setData(e.getCause());
        }
        return result;
    }

    /**
     * 文件删除
     */
    @VerifySign
    @RateLimit(limit = 5)
    @PostMapping("/delete")
    public Result deleteFile(List<String> ids ,@RequestHeader("Authorization") String token) {
        Result result = new Result();
        try {
            JwtInfo jwtInfo = jwtRedistService.getUserInfo(token);
            return fileService.deleteFileService(jwtInfo,ids);
        }catch (Exception e){
            result.setCode(ResultEnum.UNKNOWNERROR.getCode());
            result.setMsg(ResultEnum.FORBIDDEN.getData());
            result.setData(e.getCause());
        }
        return result;
    }
}

 4.Entity 实体Dao

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.util.Date;

@Data
@TableName(value = "sys_file",autoResultMap = true)
public class File {
    /**
     * id
     */
    private String id;
    /**
     * 文件名称
     */
    private String name;
    /**
     * 文件路径
     */
    private String path;
    /**
     * 文件类型
     */
    private String type;
    /**
     * 文件大小
     */
    private String size;
    /**
     * 文件访问权限
     */
    private String purview;
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 更新时间
     */
    private Date updateTime;

}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.portalwebsiteservice.demos.web.Entity.File;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface FileDao extends BaseMapper<File> {
}

5.FileServiceImpl 和 FileService 业务操作

   备注:PurviewEnum 是我定义权限的封装枚举类,涉及该方法是你可以直接删除


import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.portalwebsiteservice.demos.web.Dao.FileDao;
import com.portalwebsiteservice.demos.web.Dto.JwtInfo;
import com.portalwebsiteservice.demos.web.Dto.Result;
import com.portalwebsiteservice.demos.web.Entity.File;
import com.portalwebsiteservice.demos.web.Enum.PurviewEnum;
import com.portalwebsiteservice.demos.web.Service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import static com.portalwebsiteservice.demos.web.Util.ToolUtil.bollPurviewTool;
import static com.portalwebsiteservice.demos.web.Util.ToolUtil.currentParentPath;


@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private FileDao fileDao;
    @Value("${customInfo.file.storagePath}")
    private String storagePath;


    /**
     * 文件上传
     */
    @Override
    public Result uploadFileService(MultipartFile file) {
        Result result = new Result();
        File fileMap = new File();

        String currentPath = currentParentPath();

        //创建时间
        fileMap.setCreateTime(new Date());
        fileMap.setUpdateTime(new Date());
        fileMap.setPurview(PurviewEnum.ORDINARY.getValue());
        //用户ID
        String uId = UUID.randomUUID().toString().replace("-","");
        fileMap.setId(uId);

        //文件name
        String fileName = file.getOriginalFilename();
        fileMap.setName(fileName);

        //文件大小
        String fileSize = String.valueOf(file.getSize());
        fileMap.setSize(fileSize);

        //文件类型
        String fileType = null;
        if (fileName != null) {
            fileType = fileName.substring(fileName.lastIndexOf(".")+1);
        }
        fileMap.setType(fileType);

        //文件path
        String filePathName = uId + "." + fileType;
        fileMap.setPath(filePathName);

        //拼接文件存放地址
        java.io.File dest=new java.io.File(currentPath+storagePath + filePathName);

        //判断文件路径是否存在  如果不存在就创建文件路径
        if (dest.getParentFile().exists()) dest.getParentFile().mkdirs();

        //文件保存
        try {
            FileUtil.writeBytes(file.getBytes(), currentPath+storagePath + filePathName);
            fileDao.insert(fileMap);
            result.setData(fileMap);
            result.setMsg("上传成功");
        } catch (IOException e) {
            e.fillInStackTrace();
            result.setData(e);
        }
        return result;
    }

    /**
     * 文件下载
     */
    @Override
    public ResponseEntity<FileSystemResource>  downloadFileService(JwtInfo jwtInfo, String id) {
        LambdaQueryWrapper<File> lqw = new LambdaQueryWrapper<>();
        lqw.eq(File::getId,id);
        if (jwtInfo.getPass()) {
            String[] purviewList = jwtInfo.getPurview();
            lqw.in(File::getPurview, Arrays.asList(purviewList));
        } else {
            lqw.eq(File::getPurview, PurviewEnum.ORDINARY.getValue());
        }
        File fileMap = fileDao.selectOne(lqw);
        //设置文件完整路径
        String currentPath = currentParentPath();
        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        if (fileMap!=null && jwtInfo.getPass()){
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename="+fileMap.getPath());
            try {
                // 加载文件作为资源
                java.io.File file = new java.io.File(currentPath+fileMap.getPath());
                FileSystemResource resource = new FileSystemResource(file);
                // 返回文件内容
                return ResponseEntity.ok()
                        .headers(headers)
                        .contentLength(file.length())
                        .contentType(MediaType.parseMediaType("application/octet-stream"))
                        .body(resource);
            }catch (Exception e){
                return ResponseEntity.ok()
                        .headers(headers)
                        .contentLength(0)
                        .contentType(MediaType.parseMediaType("application/octet-stream"))
                        .body(null);
            }
        }else {
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(0)
                    .contentType(MediaType.parseMediaType("application/octet-stream"))
                    .body(null);
        }
    }

    /**
     * 文件预览
     */
    @Override
    public void viewFile(String path, HttpServletResponse response){
        String currentPath = currentParentPath() + storagePath + path;
        if (!currentPath.equals(currentParentPath())) {
            try (ServletOutputStream os = response.getOutputStream()) {
                Path filePath = Paths.get(currentPath);
                byte[] b = Files.readAllBytes(filePath);
                os.write(b);
            } catch (IOException e) {
                e.fillInStackTrace();
            }
        }
    }

    /**
     * 文件查询(管理端)
     */
    @Override
    public Result queryAllFileService(JwtInfo jwtInfo, String keyword, Integer page, Integer limit) {
        Result result = new Result();
        try {
           if (jwtInfo.getPass()){
               if (bollPurviewTool(jwtInfo.getPurview(), PurviewEnum.ADMINISTRATOR.getValue())){
                   if (keyword!=null && !keyword.isEmpty()){
                       LambdaQueryWrapper<File> lqw = new LambdaQueryWrapper<>();
                       lqw.like(File::getId, keyword).or()
                               .like(File::getName, keyword).or()
                               .like(File::getType, keyword).or()
                               .like(File::getPath, keyword);
                       Page<File> pages = new Page<>(page, limit);
                       IPage<File> iPage = fileDao.selectPage(pages,lqw);
                       result.setMsg("模糊查询成功!");
                       result.setData(iPage);
                   }else {
                       Page<File> pages = new Page<>(page, limit);
                       IPage<File> iPage = fileDao.selectPage(pages,null);
                       result.setMsg("文件信息查询成功!");
                       result.setData(iPage);
                   }
               }else {
                   result.setMsg("暂无操作权限!");
                   result.setCode(400);
               }
           }else {
               result.setMsg("token令牌过期!");
               result.setCode(400);
           }
        }catch (Exception e){
            result.setData(e.getCause());
            result.setMsg("程序报错!");
            result.setCode(500);
        }
        return result;
    }

    /**
     * 文件查询(服务端)
     */
    @Override
    public Result queryFileService(JwtInfo jwtInfo, String id) {
        Result result = new Result();
       try {
           LambdaQueryWrapper<File> lqw = new LambdaQueryWrapper<>();
           lqw.eq(File::getId,id);
           if (jwtInfo.getPass()) {
               String[] purviewList = jwtInfo.getPurview();
               lqw.in(File::getPurview, Arrays.asList(purviewList));
           } else {
               lqw.eq(File::getPurview, PurviewEnum.ORDINARY.getValue());
           }
           File file = fileDao.selectOne(lqw);
           result.setMsg("文件信息查询成功!");
           result.setData(file);
       }catch (Exception e){
           result.setData(e.getCause());
           result.setMsg("程序报错!");
           result.setCode(500);
       }
        return result;
    }

    /**
     * 文件删除
     */
    @Override
    public Result deleteFileService(JwtInfo jwtInfo, List<String> ids) {
        Result result = new Result();
        if (jwtInfo.getPass()){
           int res = fileDao.deleteBatchIds(ids);
           if (res > 0){
               result.setMsg("文件删除成功!");
           }else {
               result.setMsg("文件删除失败!");
               result.setCode(400);
           }
        }else {
            result.setMsg("token令牌过期!");
            result.setCode(400);
        }
        return result;
    }


}

以上就是完整代码!!有代码问题可以咨询小编。

 代码开发不易,全开源,感谢支持!

再次感谢每一位关注、使用、贡献和支持本项目的朋友!

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

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

相关文章

OpenCV 环境配置

首先下载opencv&#xff0c;在opencv官网进行下载。 按照上面的步骤&#xff0c;点击进去 滑至底部&#xff0c;不切换至不同页&#xff0c;选择合适的版本进行下载(Window系统选择Windows版本进行下载)。 接下来以4.1.2版本为例&#xff1a; 点击之后会进入这个页面&#xff…

聚类分析 | NRBO-GMM聚类优化算法

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 (创新)NRBO-GMM聚类优化算法 (NRBO聚类优化&#xff0c;创新&#xff0c;独家) 牛顿-拉夫逊优化算法优化GMM高斯混合聚类优化算法 matlab语言&#xff0c;一键出图&#xff0c;直接运行 1.牛顿-拉夫逊优化算法(New…

STM32—BKP备份寄存器RTC实时时钟

1.BKP简介 BKP(Backup Registers)备份寄存器BKP可用于存储用户应用程序数据。当VDD&#xff08;2.0~3.6V&#xff09;电源被切断&#xff0c;他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒&#xff0c;或系统复位或电源复位时&#xff0c;他们也不会被复位TAMP…

教培机构如何向知识付费转型

在数字化时代&#xff0c;知识付费已成为一股不可忽视的潮流。面对这一趋势&#xff0c;教育培训机构必须积极应对&#xff0c;实现向知识付费的转型&#xff0c;以在新的市场环境中立足。 一、教培机构应明确自身的知识定位。 在知识付费领域&#xff0c;专业性和独特性是关键…

【Python】selenium获取鼠标在网页上的位置,并定位到网页位置模拟点击的方法

在使用Selenium写自动化爬虫时&#xff0c;遇到验证码是常事了。我在写爬取测试的时候&#xff0c;遇到了点击型的验证码&#xff0c;例如下图这种&#xff1a; 这种看似很简单&#xff0c;但是它居然卡爬虫&#xff1f;用简单的点触验证码的方法来做也没法实现 平常的点触的方…

数据迁移:如何保证在不停机的情况下平滑的迁移数据

1. 引言 数据迁移是一个常见的需求&#xff0c;比如以下的场景&#xff0c;我们都需要进行数据迁移。 大表修改表结构单表拆分进行分库分表、扩容系统重构&#xff0c;使用新的表结构来存储数据 2. 迁移准备 2.1 备份工具 2.1.1 mysqldump mysqldump 是 MySQL 自带的用于…

【计网】从零开始认识https协议 --- 保证安全的网络通信

在每个死胡同的尽头&#xff0c; 都有另一个维度的天空&#xff0c; 在无路可走时迫使你腾空而起&#xff0c; 那就是奇迹。 --- 廖一梅 --- 从零开始认识https协议 1 什么是https协议2 https通信方案2.1 只使用对称加密2.2 只使用非对称加密2.3 双方都使用非对称加密2.4 …

Winform和WPF的技术对比

WinForms&#xff08;Windows Forms&#xff09;和WPF&#xff08;Windows Presentation Foundation&#xff09;是用于创建桌面应用程序的两种技术。尽管两者都可以用于开发功能强大的Windows应用程序&#xff0c;但它们的设计理念、功能和开发体验都有显著区别。在本文中&…

(亲测可行)ubuntu下载安装c++版opencv4.7.0和4.5.0 安装opencv4.5.0报错及解决方法

文章目录 &#x1f315;系统配置&#x1f315;打开终端&#xff0c;退出anacoda激活环境(如果有的话)&#x1f315;安装依赖&#x1f319;安装g, cmake, make, wget, unzip&#xff0c;若已安装&#xff0c;此步跳过&#x1f319;安装opencv依赖的库&#x1f319;安装可选依赖 …

Smartfusion2开发环境的搭建

Libero软件安装包括libero安装、bibero补丁安装、bibero的license添加和官方ip库的添加等4部分内容组成。具体内容如下所示&#xff1a; 1 Libero软件安装 1、解压LiberoSoC_v11.8的安装包到当前目录&#xff0c;然后运行Libero中的可执行软件进行安装&#xff1b; 图1 双击l…

Javascript实现Punycode编码/解码

Punycode编码/解码的Javascript实现。 用法 const punycode require(punycode); console.log(punycode.encode(用法)); //nwwn1p console.log(punycode.decode(nwwn1p)) //用法console.log(punycode.toIDN(用法.中国)); //xn--nwwn1p.xn--fiqs8s console.log(punycode.fromI…

【AAOS】Android Automotive 13模拟器源码下载及编译

源码下载 repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r69 repo sync -c --no-tags --no-clone-bundle 源码编译 source build/envsetup.sh lunch sdk_car_x86_64-userdebug make -j8 运行效果 emualtor HomeMapAll appsSettings…

CUDA-X

NVIDIA CUDA-X 文章目录 前言一、CUDA-X 微服务CUDA-X 微服务CUDA-X 库二、CUDA-X 数据处理三、CUDA-X AI四、CUDA-X HPC总结前言 适用于 AI 的采用 GPU 加速的微服务和库。 释放 GPU 在 AI 应用程序中的潜能 探索 NVIDIA CUDA-X AI 正在推动变革的 AI 领域和可在其中使用的 G…

win10 解决Qt编译得到的可执行文件 *.exe 无法启动的问题

问题描述 在Qt 5.12.4 写了一个服务端程序&#xff0c;编译可以通过&#xff0c;但是打开debug目录下的可执行文件&#xff0c;就报以下错误&#xff1a; 解决方案 方法一 复制缺失的dll到TCPServer.exe目录下 方法二 可能是系统环境变量没有配好 将你电脑上的Qt安装目录…

linux入门——“权限”

linux中有权限的概念&#xff0c;最常见的就是安装一些命令的时候需要输入sudo来提权&#xff0c;那么为什么要有这个东西呢&#xff1f; linux是一个多用户操作系统&#xff0c;很多东西看起来是有很多分&#xff0c;但是实际的存储只有一份&#xff08;比如命令&#xff0c;不…

网站在对抗机器人攻击的斗争中失败了

95% 的高级机器人攻击都未被发现&#xff0c;这一发现表明当前的检测和缓解策略存在缺陷。 这表明&#xff0c;虽然一些组织可能拥有基本的防御能力&#xff0c;但他们没有足够的能力应对更复杂的攻击。 例如利用人工智能和机器学习来模仿人类行为的攻击。 这些统计数据强调…

数据结构之顺序表详解:从原理到C语言实现

引言 在上一篇文章中我们讲到了时间复杂度与空间复杂度&#xff0c;今天我们接着讲数据结构中的内容。 数据的存储和组织方式决定了程序的效率。而顺序表&#xff0c;也就是大家熟悉的数组&#xff0c;正是我们编程中的“起步工具”。它简单易懂&#xff0c;却能帮你解决许多…

python利用电脑默认打开方式打开文件,视频,图片

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理python利用os库打开本地文件的方法。 这个确实比较简单。 利用os库的 os.startfile("mp4") 函数即可用系统默认打开方式打开文件。 这里打开视频进行测试。 import os os.startfile("…

linux 虚拟环境下源码安装DeepSpeed

第一步&#xff1a;创建虚拟环境&#xff1a; conda create -n deepspeed python3.10 第二步&#xff1a;进入虚拟环境&#xff0c;安装Pytorch 2.3.1 # CUDA 12.1 conda install pytorch2.3.1 torchvision0.18.1 torchaudio2.3.1 pytorch-cuda12.1 -c pytorch -c nvidia 第…

谷粒商城(学习笔记)

配置刷新的注解 数据表中不存在的数据 gateway路径重写 CORS跨域 调整路由顺序&#xff1a; TODO是什么:备忘录 逻辑删除 axios有请求缓存&#xff1a; 请求的模版&#xff01; 删除成功后&#xff0c;重新获取数据&#xff01; 删除成功之后&#xff0c;还有提示消息 删除成功…