【easy云盘 | day08】目录相关操作 + 移动和下载文件


在这里插入图片描述

前言

再次重申,本项目非原创,视频来源于:
Springboot项目实战 easypan 仿百度网盘 计算机毕业设计 简历项目 项目经验(后端)

再次重申:本人不分享项目源码,支持项目付费!!

回顾

之前已经完成了分片文件的合并、视频文件切割、生成缩略图,以及文件预览等业务,接下来关于文件还有创建目录,文件重命名,移动文件等操作。本次笔记记录这些后续操作的实现过程。

完成任务

1. 创建目录

controller 层实现:
在这里插入图片描述

创建目录需要传入文件父id,因为有的目录直接在根目录下创建,而有的目录则是在已存在的目录下创建的。还需要传入文件名 fileName。session 用户获取当前登录用户的信息。

service 层实现:
在这里插入图片描述
正式创建目录前,需要对创建的目录文件名进行校验检查当前用户当前父级目录下是否有同名的目录文件
在这里插入图片描述

2. 获取目录路径

在点击更深层目录下时,应当在页面上方显示当前的目录路径:
在这里插入图片描述
请求时的负载中会传入走过的所有目录id,中间用 “/” 隔开
在这里插入图片描述
controller 层实现:
在这里插入图片描述
将这个功能的具体实现过程写在了当前 controller 类的父类 CommonFileController 类中,所以调用时使用 super:
在这里插入图片描述

  • 为什么要将查询的数据转换为 FileInfoVO 对象再返回?
    VO 代表视图对象(View Object),通常用于与前端交互,封装需要展示给用户的简要信息。直接返回内部数据结构 FileInfo,可能会暴露一些不必要的或敏感的信息。

3. 文件重命名

controller 层代码实现:
在这里插入图片描述
对文件进行重命名需要从前端获取重命名文件的 id,以及文件要重名为什么名称的 fileName。

service 层代码实现:
在这里插入图片描述

  • 这里我一开始比较疑惑,为什么在更新数据库之前,已经对传入的文件名进行校验,检验当前用户在同一目录下是否有与之同名的文件,在更新数据库之后,还要再次检查?
    这与并发操作有关。在高并发或多用户的环境中,可能有操作出现重叠。其次,有些场景中,文件夹可能是共享的,这种情况下多个用户访问同一个文件夹的可能性会增加。此时,例如,用户 A 正在重命名文件时,而在数据库更新前,用户 B 可能已经在同一目录下创建了同名文件。这种情况下,如果不进行第二次检验,就会导致在同一目录下出现同名文件。

4. 获取所有目录

当我们选择文件要将它进行移动时,在点击移动文件后,应显示当前父目录下的所有目录。
在这里插入图片描述
controller 层代码实现:
在这里插入图片描述

注意:如果要移动的文件中包含目录,需要在展示的目录中排除要移动的目录本身,因为一个目录移动到自身,这是没有任何意义的,不符合常规做法。

xml 文件中针对要排除的目录,需要增加下面的约束:
在这里插入图片描述

5. 移动文件

controller 层代码实现:
在这里插入图片描述

service 层实现:
在这里插入图片描述
这里的实现过程较为复杂:
(1)检查要移动到的目标目录是否是自身目录下,目标目录是否处于正常使用状态。
(2)查询当前用户目标目录下的所有文件。并将其以文件名为 key,文件对象为 value 存入 Map 中。
(3)根据文件 id 和用户 id 查询所选中的文件,遍历每个文件,查看目标目录下的文件 Map 中是否存在与之同名的文件,若存在,则要重命名所选的文件。再更新数据库中的文件信息。

6. 创建下载链接

在点击下载文件时,会首先创建一个下载链接,实际是生成一个下载链接的唯一标识码。那么,为什么在文件正式下载前创建下载链接?

  • 首先,是针对系统的安全性,直接提供文件路径可能会暴露文件的实际位置,有安全风险,使用下载链接可以限制用户对系统的直接访问。
  • 其次,生成下载连接可以设置有效期,是链接在一定时间内有效,过期后自动失效,这有助于控制文件的访问。

controller 层实现:
在这里插入图片描述

父层的 createDownloadUrl() 方法:
在这里插入图片描述
需要将下载链接的代码和对应的文件信息保存在 Redis 中,以便在下载文件时从 Redis 中或文件信息。

DownloadFileDto类:(其实就是一个文件下载时的数据传输对象)
在这里插入图片描述

7. 下载文件

controller 层实现:
在这里插入图片描述

父层的 download() 方法:
在这里插入图片描述
根据下载链接码从 Redis 中获取对应的下载文件信息,获取该文件在服务器中的存放路径以及文件名,将其作为响应返回给客户端。

这段代码我直接粘贴在下面,以便后续使用:

/**
     * 下载文件
     */
    protected void download(HttpServletRequest request, HttpServletResponse response, String code) throws Exception{
        DownloadFileDto downloadFileDto = redisComponent.getDownloadCode(code);

        if (null == downloadFileDto){
            return;
        }
        String filePath = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + downloadFileDto.getFilePath();
        String fileName = downloadFileDto.getFileName();


        // 设置HTTP响应内容类型为application/octet-stream,表示文件下载
        response.setContentType("application/x-msdownload; charset=UTF-8");
        // 处理不同浏览器对文件名的兼容性
        // request.getHeader("User-Agent")获取到请求头的用户代理,并转换为小写
        // 检查用户代理字符串中是否包含"msie",包含则说明是 IE 浏览器
        if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > 0) { // IE浏览器
            // IE浏览器对文件名进行了URL编码,确保文件名中的特殊字符(空格、中文等)在URL中是安全的
            fileName = URLEncoder.encode(fileName, "UTF-8");
        }  else {
            // 其他浏览器使用ISO8859-1编码
            fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
        }
        // 设置响应头Content-Disposition,告知浏览器以附件形式下载,并指定下载时的文件名
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        readFile(response, filePath);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值