当前位置: 首页 > news >正文

Easy云盘总结篇-文件上传01

说在前面:此项目是跟着B站一位大佬做的,不分享源码,支持项目付费

文章目录

    • 文件列表
    • 文件上传
      • 文件秒传
      • 分片上传
      • 文件合并
      • 视频切割
    • 缩略图

文件列表

在这里插入图片描述
在这里插入图片描述
这段的逻辑

前端传过来query,包含用户上传文件的相关内容,和类型category

然后通过枚举类FileCategoryEnums进行文件类型识别,如果找到对应枚举,就设置好文件类型

然后就是设置好用户id,和排序顺序,文件使用情况(使用中)

将查询到的用户文件以PaginationResultVO返回,其中PaginationResultVO的list装FileInfo

然后需要返回给前端FileInfoVo类型而并非实体类类型FileInfo,所以这里编写了一个类型转换方法:convert2PaginationVo

protected <S,T> PaginationResultVO<T> convert2PaginationVo(PaginationResultVO<S> result,Class<T>  classz ) {PaginationResultVO<T> resultVO=new PaginationResultVO<>();resultVO.setList(CopyTools.copyList(result.getList(),classz));resultVO.setPageNo(result.getPageNo());resultVO.setPageSize(result.getPageSize());resultVO.setPageTotal(result.getPageTotal());resultVO.setTotalCount(result.getTotalCount());return resultVO;}

这个逻辑就是将PaginationResultVO里的list类型进行s换为t,其他数据直接复制过去的过程。

文件上传

这个逻辑蛮复杂,文件上传分普通上传(第一次传)和秒传(上传相同文件)。其中还需要对文件进行分片处理,过大的文件就需要拆分成小的分片逐步上传。
在这里插入图片描述

文件秒传

在这里插入图片描述在这里插入图片描述
这段的逻辑:

当分片为0,也就是传过来第一个分片时,进行文件是否在库里的判断,如果有,就秒传。

这里判断秒传:根据md5值查询到第一页使用中的文件

如果不为空,则实现秒传:

先判断当前使用空间+文件大小是否>总空间,抛出对应异常

最后就是将文件进行属性赋值,再将文件插入到表中更新用户空间。

当时有个疑惑点:为什么秒传文件是insert而不是update,现在一想,明白如果update那么意味着该用户始终只有一个文件,而他上传的相同文件相当于覆盖了之前的文件,不符合逻辑。

然后就是说明文件的重命名问题:
在这里插入图片描述

分片上传

在前面如果不实现秒传,则进行分片上传
在这里插入图片描述
这段逻辑:

当第一个分片来时,先判断是否需要秒传,不是的话执行后面分片上传。当第2第3等分片来时,不再判断秒传,直接分片上传。

分片上传,先判断空间大小,这里,因为是分片,所有就创建了临时文件大小,临时空间(已经上传了的分片大小)+用户已存文件空间+文件大小(当前分片文件大小)>总空间,就抛出异常。

然后分片文件没上传完时,dto要设置状态为“上传中”,并且保存当前分片的临时大小。

假如5个分片,当前分片如果是4时,就已经上传完成了,不走if。

最后,当最后一个分片也上传后:
在这里插入图片描述

文件合并

因为我们上传的是一个一个的分片,临时存储在temp文件夹中,还需要将这些分片合并,才是真正实现上传了文件。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这段逻辑:

在最后一个分片上传之前的分片,只是设置了上传状态和保存临时分片大小。在最后一个分片上传后,创建FileInfo,将整个文件的信息进行属性填充,插入到数据库文件表中。

然后更新用户当前空间。

最后如果没上传成功或者临时存放文件夹都没有,就上传失败,删除文件夹。

在事务提交后,执行异步合并文件。

异步

异步通常指的是非阻塞的操作,也就是说在合并分片的过程中,不需要等待所有分片都准备好才开始处理,而是可以一边接收分片一边处理,或者在后台进行合并操作,不影响主线程或其他任务的执行。
转码过程:

转码

转码(Transcoding)是指将数据从一种编码格式转换为另一种编码格式的过程,通常用于适配不同设备、平台或需求。其核心目标是解决兼容性问题优化数据存储/传输效率

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这段逻辑:

通过传过来的源路径,找到需要合并的文件,然后listFiles()获取到这个路径下的这个文件的所有分片。然后就是就是io不断的读取所有的分片文件,把所有的数据都存储到目标文件中。

listFiles()

获取目录下的文件和子目录

RandomAccessFile

RandomAccessFile 是Java中用于访问文件的类,它允许随机访问文件,即可以跳转到文件的任意位置进行读写操作。这一特性使得 RandomAccessFile 在需要访问文件的部分内容时非常有用,而不是从头到尾完整地读取文件

视频切割

在这里插入图片描述

为什么要视频切割:
可以按需加载和播放视频,而不需要一次性下载完整的视频文件,从而提高视频的加载速度和播放效率

在这里插入图片描述
在这里插入图片描述
这段的逻辑:

将视频先转换成一个大的index.ts文件,然后再将它切割成几个小的ts文件和一个.m3u8索引文件(类似目录),最后删除index.ts文件。

缩略图

一般图片类型和视频需要做缩略图:
在这里插入图片描述
在这里插入图片描述
无论转码成功与否,将整个文件的文件大小,文件缩略图,文件状态(使用中/转码失败),进行文件更新,
这里通过对老状态(转码中)的限制,只有当数据库中文件的当前状态等于 oldStatus 时,才会执行状态更新。若此时状态已被其他线程修改,则更新失败(不会影响数据)。避免了转码流程中的状态覆盖和顺序错乱问题。这就是乐观锁。
在这里插入图片描述

生成缩略图这里主要是FFmpeg命令行知识

/*** 为视频生成封面图(通过截取视频的一帧画面)* @param sourceFile 原始视频文件(输入文件)* @param width 生成封面图的目标宽度(高度会根据原始视频宽高比自动计算)* @param targetFile 生成的封面图文件(输出文件)*/public static void createCover4Video(File sourceFile, Integer width, File targetFile) {try {// FFmpeg 命令模板说明:// -i: 指定输入文件(原始视频)// -y: 覆盖已存在的输出文件(避免冲突)// -vframes 1: 仅提取1帧画面(作为封面)// -vf scale=%d:%d/a: 视频过滤(Video Filter)参数,设置缩放规则//   第一个%d: 目标宽度(传入的width)//   第二个%d/a: 高度按原始宽高比自动计算(保持比例避免画面变形)// %s: 输出文件路径(生成的封面图)String cmd = "ffmpeg -i %s -y -vframes 1 -vf scale=%d:%d/a %s";// 格式化命令并执行(通过ProcessUtils工具类调用系统命令)// 第二个参数false表示不等待命令执行完成(异步执行)ProcessUtils.executeCommand(String.format(cmd,sourceFile.getAbsoluteFile(),  // 原始视频路径width,                         // 目标宽度width,                         // 用于计算高度的基准值(与宽度相同以保持比例)targetFile.getAbsoluteFile()   // 封面输出路径),false);} catch (Exception e) {// 记录生成封面失败的异常信息(包括堆栈跟踪)logger.error("生成视频封面失败", e);}}
/*** 使用 FFmpeg 为图片生成缩略图(仅当原始图片宽度超过指定阈值时触发压缩)* @param file 原始图片文件(输入文件)* @param thumbnailWidth 缩略图的目标宽度(高度自动按比例计算)* @param targetFile 生成的缩略图文件(输出文件)* @param delSource 是否删除原始图片文件(true: 删除;false: 保留)* @return 布尔值,表示是否执行了压缩操作(true: 执行了压缩;false: 未压缩,因原始宽度未超过阈值)*/public static Boolean createThumbnailWithFfmpeg(File file, int thumbnailWidth, File targetFile, Boolean delSource) {try {// 读取原始图片的宽高信息(通过ImageIO读取图片元数据)BufferedImage src = ImageIO.read(file);// 注意:若ImageIO无法读取该图片格式(如WebP、HEIC等非标准格式),src会为null,后续操作会抛出空指针异常// 获取原始图片的宽度和高度int sorceW = src.getWidth();   // 原始宽度int sorceH = src.getHeight();  // 原始高度// 关键逻辑:若原始宽度 <= 目标缩略图宽度,无需压缩,直接返回falseif (sorceW <= thumbnailWidth) {return false;}// 调用压缩方法(实际通过FFmpeg执行缩放操作)compressImage(file, thumbnailWidth, targetFile, delSource);return true;  // 标记已执行压缩} catch (Exception e) {// 打印异常堆栈(实际生产环境建议替换为日志记录)e.printStackTrace();}return false;  // 异常时返回未压缩}/*** 使用 FFmpeg 压缩图片(按指定宽度缩放,高度自动保持比例)* @param sourceFile 原始图片文件(输入文件)* @param width 目标宽度(高度自动按原始宽高比计算)* @param targetFile 压缩后的图片文件(输出文件)* @param delSource 是否删除原始文件(true: 删除;false: 保留)*/public static void compressImage(File sourceFile, Integer width, File targetFile, Boolean delSource) {try {// FFmpeg 命令模板说明:// -i: 指定输入文件(原始图片)// -vf scale=%d:-1: 视频过滤参数,设置缩放规则//   %d: 目标宽度(传入的width)//   -1: 高度自动计算(保持原始宽高比例)// %s: 输出文件路径(压缩后的图片)// -y: 覆盖已存在的输出文件String cmd = "ffmpeg -i %s -vf scale=%d:-1 %s -y";// 格式化并执行命令ProcessUtils.executeCommand(String.format(cmd,sourceFile.getAbsoluteFile(),  // 原始图片路径width,                         // 目标宽度targetFile.getAbsoluteFile()   // 压缩后输出路径),false);// 若需要删除原始文件,则通过FileUtils强制删除(注意:需确保文件未被其他进程占用)if (delSource) {FileUtils.forceDelete(sourceFile);}} catch (Exception e) {// 记录压缩失败的异常信息(不记录堆栈,仅记录错误信息)logger.error("压缩图片失败");}}

相关文章:

  • 高等数学-第七版-下册 选做记录 习题10-2
  • LangChain4J-XiaozhiAI 项目分析报告
  • FiLo++的框架图介绍
  • Sway初体验
  • SwinTransformer 改进:与PSConv结合的创新设计
  • Go-Spring 全新版本 v1.1.0
  • 代码随想录算法训练营第八天 |【字符串】344.反转字符串、541. 反转字符串II、卡码网:54.替换数字
  • 互联网与无线广播:数字时代与模拟时代的通讯双轨制-优雅草卓伊凡
  • 使用synchronized关键字同步Java线程
  • Vector - VT System - 板卡_VT板卡使用介绍_07
  • BUUCTF Pwn wustctf2020_closed WP
  • Java大师成长计划之第12天:性能调优与GC原理
  • 设计模式每日硬核训练 Day 17:中介者模式(Mediator Pattern)完整讲解与实战应用
  • LeetCode - 91.解码方法
  • 高等数学第三章---微分中值定理与导数的应用(3.3泰勒(Taylor)公式)
  • transfomer网络构建
  • C与指针——输入输出
  • 【学习笔记】深度学习:典型应用
  • LlamaIndex统一管理存储组件的容器--StorageContext
  • ES类的索引轮换
  • 抚州一原副县长拉拢公职人员组建“吃喝圈”,长期接受打牌掼蛋等“保姆式”服务
  • 美国将于6月14日举行阅兵式,美媒报当天是特朗普生日
  • 山东一景区怕游客赶不到海撒三千斤蛤蜊:给游客提供情绪价值
  • 购车补贴、“谷子”消费、特色产品,这些活动亮相五五购物节
  • 全国台联原会长杨国庆逝世,享年89岁
  • 证监会副主席王建军被查