1.獲取文件列表
流程:前端根據查詢條件封裝查詢信息,后端接收后進行封裝,封裝為FileInfoQuery,根據fileInfoQuery使用mybatis的動態sql來進行查詢。
2.文件分片上傳
每次上傳需要上傳包括(文件名字,文件,md5值,父文件id,當前是哪一個分塊,總的分塊數量)
流程:
? ? ? ?第一次上傳的時候后端生成fileId(后續返回給前端,后面的分片都會帶上這個fileId)。
? ? ? ?秒傳邏輯:
?????????當chunk = 0,也就是第一個分片,會先拿著md5去數據庫里面里面進行查詢,如果查詢的數據不為空,那么就可以秒傳。秒傳前先從redis里面獲取用戶的空間是否滿足,不滿足就拋出異常,空間充足就構造文件信息插入到數據庫中,接著更新用戶的空間,返回上傳成功的狀態信息(秒傳)。
? ? ? ? 正常邏輯(不能秒傳):
????????首先判斷用戶空間是否足夠插入當前的分片,不夠的話拋出異常。接著構建臨時目錄(由用戶id和fileId構成),創建臨時文件(命名規則是當前的chunk值),使用File.copy來進行文件的復制(在這里可以使用我們的限流器)。上傳成功后,將已經保存的臨時文件的大小存儲在redis當中方便后面判斷空間是否充足。
? ? ? ? 如果當前上傳后不是最后一個分片,那么返回狀態為上傳中,前端會繼續發請求。
? ? ? ? 如果最后一個分片上傳完成,構架file信息,根據redis中臨時文件的大小來更新用戶已使用空間。返回狀態信息為上傳完成。如果中間文件上傳失敗,在finally中刪除臨時文件。
? ? ? ? 當事物提交完成之后,異步的合并文件。
? ? ? ? 異步合并的流程:
? ? ? ? ? ? ? ? 判斷數據庫中是否已經正常插入,如果沒有插入直接返回。構建真實文件路徑和文件名,使用 RandomAccessFile來進行文件的合并并且產出源文件(臨時文件)。接著根據文件的類型判斷是否是視頻或者圖片,如果是視頻對視頻進行切割,生成縮略圖。如果是圖片生成縮略圖。
? ? ? ? ? ? ? ? 在finally根據根據一個transferSuccess字段判斷是否合并成功,如果合并失敗就更改數據庫為轉碼失敗狀態,否則就更改為使用中的狀態。
?
知識點:
怎么實現事物提交后才開始異步合并?
Spring 提供的 事務同步管理器,用于管理事務的回調機制。
它允許開發者在事務的不同階段(提交前、提交后、回滾后等)執行額外的操作。
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCommit() {fileInfoService.transferFile(fileInfo.getFileId(), webUserDto);}});
異步是怎么實現的:
@async注解實現異步合并,他的原理是aop,當調用這個方法的時候,其實是調用的代理方法,將其放到默認線程池中執行。
但是不推薦使用默認線程池,所以可以自定義線程池。
因為當前的項目中異步合并包括合并文件和圖片壓縮,視頻處理。所以定義的線程池的核心線程數是(cpu核心數),最大線程數是(cpu核心數*2),并使用有界隊列來作為任務隊列。
RandomAccessFile實現文件合并:
RandomAccessFile
?是 Java 中用于隨機訪問文件的類,它允許直接跳轉到文件的任意位置進行讀寫操作(類似操作內存中的數組),而不是像普通?InputStream
/OutputStream
?那樣只能順序讀寫。
使用ffmpeg來進行視頻切割和圖片縮略圖生成:
核心代碼
-
?創建切片目錄
- 根據原始視頻文件名,創建一個同名目錄(例如?
video.mp4
?對應?video/
?目錄),用于存放切片文件。
- 根據原始視頻文件名,創建一個同名目錄(例如?
-
?檢測視頻編碼格式
- 使用?
ffprobe
?檢測視頻的編碼格式(如 H.264、H.265/HEVC)。 - 如果視頻是 ?HEVC(H.265)編碼,則先將其轉碼為 ?H.264 編碼?(因為某些播放器不支持 H.265)。
- 使用?
-
?生成中間 TS 文件
- 通過?
ffmpeg
?將視頻轉換為 ?TS 格式?(MPEG-TS,流媒體常用容器格式)。
- 通過?
-
?切割 TS 文件并生成索引
- 將 TS 文件按 ?30秒一段?切割成多個小切片(如?
xxx_0001.ts
、xxx_0002.ts
)。 - 生成?
.m3u8
?索引文件,記錄所有切片的順序和路徑。
- 將 TS 文件按 ?30秒一段?切割成多個小切片(如?
-
?清理臨時文件
- 刪除中間生成的完整 TS 文件(僅保留切片和索引)。
怎么執行的cmd命令:
? ? ? ? 從網上找的一個工具類進行封裝ProcessUtils。
3.讀取圖片
String contentType = "image/" + imageSuffix;
//設置響應頭,表示是圖片,防止被當作二進制文件下載response.setContentType(contentType);
//讓瀏覽器或者cdn進行緩存,后續可以直接查詢緩存response.setHeader("Cache-Control", "max-age=2592000");
?