基于springboot的文件上傳系統:重新定義大文件傳輸的可靠性邊界

一、文件分塊上傳解析

1、為什么傳統文件上傳已經無法滿足現代需求?

在云原生時代,文件上傳不再是簡單的"選擇文件-點擊上傳"的過程。隨著視頻、設計圖、數據集等大文件的普及,傳統的單文件上傳方式面臨著諸多挑戰:

  • 網絡不穩定導致的上傳失敗:一個幾GB的視頻文件,上傳到99%時網絡斷開,前功盡棄
  • 并發上傳的資源競爭:多個大文件同時上傳時,服務器資源被耗盡
  • 缺乏可觀測性:無法了解上傳進度、失敗原因和系統健康狀態
  • 用戶體驗差:無法暫停、恢復或查看詳細進度

本文將深入剖析企業級分布式文件上傳系統,展示如何通過**分批分塊上傳**和**全棧監控**來解決這些痛點。

2、多維度文件上傳架構

?2.1、?分塊上傳:化整為零的智能策略

傳統的文件上傳是"all-or-nothing"的模式,而本文采用了**分塊上傳**的策略,將大文件分割成多個小塊(默認5MB),每個塊獨立上傳和校驗。

// 分塊上傳的核心邏輯@Transactionalpublic ChunkUploadResponse uploadChunk(ChunkUploadRequest request) throws IOException {// 驗證文件標識符FileInfo fileInfo = fileInfoRepository.findByFileIdentifier(request.getFileIdentifier()).orElseThrow(() -> new RuntimeException("文件標識符無效"));// 驗證分塊MD5String actualMd5 = calculateMd5(request.getChunkFile().getBytes());if (!actualMd5.equals(request.getChunkMd5())) {throw new RuntimeException("分塊MD5校驗失敗");}// 保存分塊文件saveChunkFile(fileInfo, request.getChunkNumber(), request.getChunkFile());// 檢查是否所有分塊都已上傳完成long uploadedChunks = fileChunkRepository.countUploadedChunks(fileInfo.getId());boolean completed = uploadedChunks == fileInfo.getTotalChunks();if (completed) {// 合并文件mergeChunks(fileInfo);fileInfo.setStatus(UploadStatus.COMPLETED);// 記錄監控指標metricsService.incrementFileUpload(fileType, fileInfo.getFileSize());}return ChunkUploadResponse.builder().success(true).completed(completed).progress(calculateProgress(fileInfo.getId())).build();}

圖解:

設計的優勢:

  • 容錯性:單個分塊失敗不影響整體上傳
  • 并發性:多個分塊可以并行上傳
  • 可恢復性:支持斷點續傳,已上傳的分塊不會丟失

2.2. 批量上傳:突破單文件限制

批量文件上傳,允許用戶同時上傳多個文件,每個文件都采用分塊策略:

@Transactionalpublic BatchFileUploadInitResponse batchInitFileUpload(BatchFileUploadInitRequest request, Long userId) {List<FileUploadInitResponse> responses = new ArrayList<>();for (FileUploadInitRequest fileRequest : request.getFiles()) {try {FileUploadInitResponse response = initFileUpload(fileRequest, userId);responses.add(response);} catch (Exception e) {// 單個文件初始化失敗不影響其他文件log.error("文件初始化失敗: {}", fileRequest.getFileName(), e);}}return BatchFileUploadInitResponse.builder().results(responses).totalFiles(request.getFiles().size()).successfulFiles(responses.size()).build();}

優點:

  • 一次性選擇多個文件進行上傳
  • ?獨立控制每個文件的上傳狀態(暫停、恢復、刪除)
  • ?獲取整體和單個文件的進度信息

?

2.3. 智能去重:MD5哈希秒傳機制

? 實現基于MD5哈希的文件去重機制,相同內容的文件只需存儲一份:

// 檢查是否已存在相同MD5的文件Optional<FileInfo> existingFile = fileInfoRepository.findByMd5Hash(request.getMd5Hash());if (existingFile.isPresent() && existingFile.get().getStatus() == UploadStatus.COMPLETED) {return FileUploadInitResponse.builder().fileIdentifier(existingFile.get().getFileIdentifier()).shouldResume(false).fileExists(true).message("文件已存在,無需重復上傳").progress(100.0).build();}

? ? 設計優點: 提升了用戶體驗和存儲效率,實現了真正的"秒傳"功能。

三、?監控體系:全棧可觀測性的最佳實踐

?1. 自定義指標:業務價值的量化

一個好的文件上傳系統,更是一個可觀測的文件上傳系統。通過Spring Boot Actuator + Micrometer + Prometheus的組合,實現了細粒度的監控:

@Servicepublic class MetricsService {// 核心業務指標private final Counter fileUploadCounter;private final Counter fileDownloadCounter;private final Counter fileDownloadErrorCounter;private final AtomicLong activeConnections = new AtomicLong(0);private final AtomicLong totalStorageSize = new AtomicLong(0);public MetricsService(MeterRegistry meterRegistry) {this.fileUploadCounter = Counter.builder("file.upload.count").description("文件上傳總數").register(meterRegistry);// 注冊Gauge指標Gauge.builder("active.connections", activeConnections, AtomicLong::doubleValue).description("活躍連接數").register(meterRegistry);Gauge.builder("storage.total.size", totalStorageSize, AtomicLong::doubleValue).description("總存儲大小(字節)").register(meterRegistry);}}

監控設計圖:

?2. AOP監控切面:無侵入式的性能追蹤

通過AOP切面,可實現了對所有Controller方法的自動監控,無需修改業務代碼:

/*** 監控所有Controller方法*/@Around("@within(org.springframework.web.bind.annotation.RestController)")public Object monitorControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable {Timer.Sample sample = metricsService.startTimer();String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getSimpleName();String status = "success";try {// 增加活躍連接數metricsService.incrementActiveConnections();// 執行方法Object result = joinPoint.proceed();// 記錄特定操作recordSpecificOperations(methodName, joinPoint.getArgs());return result;} catch (Exception e) {status = "error";metricsService.recordBusinessError(methodName, e.getClass().getSimpleName());throw e;} finally {// 減少活躍連接數metricsService.decrementActiveConnections();// 獲取HTTP請求信息try {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (attributes != null) {HttpServletRequest request = attributes.getRequest();String method = request.getMethod();String uri = request.getRequestURI();// 記錄API請求metricsService.recordApiRequest(sample, method, uri, status);}} catch (Exception e) {log.warn("無法獲取HTTP請求信息", e);}}}

3. 多層級監控棧:從數據到告警的完整鏈路

一個文件上傳的完整的監控棧:

  • Prometheus:指標采集和存儲
  • Grafana:可視化展示
  • AlertManager:告警管理
  • 釘釘Webhook:即時通知

這個監控棧要做到:

  • 實時監控文件上傳下載的成功率
  • 追蹤API響應時間和錯誤率
  • 監控存儲空間使用情況
  • 在異常發生時及時告警

監控圖:

?

?

四、 技術架構:云原生時代的最佳實踐

1. 容器化部署:一鍵啟動的完整環境

采用Docker Compose進行容器化部署,包含了完整的技術棧:

version: '3.8'services:# MySQL 數據庫mysql:image: mysql:8.0container_name: boot4-mysqlenvironment:MYSQL_ROOT_PASSWORD: nextera123MYSQL_DATABASE: boot4MYSQL_USER: boot4userMYSQL_PASSWORD: boot4passports:- "3306:3306"volumes:- mysql_data:/var/lib/mysql- ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sqlcommand: --default-authentication-plugin=mysql_native_passwordnetworks:- boot4-network# Elasticsearchelasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.18.0container_name: boot4-elasticsearchenvironment:- discovery.type=single-node- "ES_JAVA_OPTS=-Xms512m -Xmx512m"- xpack.security.enabled=false- xpack.security.enrollment.enabled=falseports:- "9200:9200"volumes:- elasticsearch_data:/usr/share/elasticsearch/datanetworks:- boot4-network# Prometheusprometheus:image: prom/prometheus:latestcontainer_name: boot4-prometheuscommand:- '--config.file=/etc/prometheus/prometheus.yml'- '--storage.tsdb.path=/prometheus'- '--web.console.libraries=/etc/prometheus/console_libraries'- '--web.console.templates=/etc/prometheus/consoles'- '--storage.tsdb.retention.time=15d'- '--web.enable-lifecycle'ports:- "9090:9090"volumes:- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml- ./monitoring/alert-rules.yml:/etc/prometheus/alert-rules.yml- prometheus_data:/prometheusdepends_on:- boot4-app- alertmanagernetworks:- boot4-network# Alertmanageralertmanager:image: prom/alertmanager:latestcontainer_name: boot4-alertmanagercommand:- '--config.file=/etc/alertmanager/alertmanager.yml'- '--storage.path=/alertmanager'- '--web.external-url=http://localhost:9093'- '--web.route-prefix=/'ports:- "9093:9093"volumes:- ./monitoring/alertmanager.yml:/etc/alertmanager/alertmanager.yml- alertmanager_data:/alertmanagerdepends_on:- dingtalk-webhooknetworks:- boot4-network# 釘釘 Webhook 代理服務dingtalk-webhook:build:context: ./monitoringdockerfile: Dockerfile.webhookcontainer_name: boot4-dingtalk-webhookports:- "8090:8090"environment:- DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/robot/send?access_token=YOUR_DINGTALK_TOKENnetworks:- boot4-network# Grafanagrafana:image: grafana/grafana:latestcontainer_name: boot4-grafanaenvironment:- GF_SECURITY_ADMIN_USER=admin- GF_SECURITY_ADMIN_PASSWORD=admin123- GF_USERS_ALLOW_SIGN_UP=falseports:- "3000:3000"volumes:- grafana_data:/var/lib/grafana- ./monitoring/grafana/provisioning:/etc/grafana/provisioning- ./monitoring/grafana/dashboards:/var/lib/grafana/dashboardsdepends_on:- prometheusnetworks:- boot4-network# 應用程序boot4-app:build:context: .dockerfile: Dockerfilecontainer_name: boot4-appenvironment:- SPRING_PROFILES_ACTIVE=docker- MYSQL_HOST=mysql- MYSQL_PORT=3306- MYSQL_DATABASE=boot4- MYSQL_USERNAME=boot4user- MYSQL_PASSWORD=boot4pass- ELASTICSEARCH_HOST=elasticsearch- ELASTICSEARCH_PORT=9200ports:- "8080:8080"depends_on:- mysql- elasticsearchvolumes:- ./uploads:/app/uploads- ./logs:/app/logsnetworks:- boot4-networkvolumes:mysql_data:elasticsearch_data:prometheus_data:grafana_data:alertmanager_data:networks:boot4-network:driver: bridge 

2. 多存儲支持:適應不同場景的需求

一個好的文件上傳要設計靈活的存儲架構:

  • MySQL:文件元數據和分塊信息
  • 文件系統:實際文件內容存儲
  • ElasticSearch:日志和搜索

?3. 安全性:企業級的權限控制

系統集成了JWT認證和權限控制:

    /*** 初始化文件上傳*/@PostMapping("/upload/init")@LogRecord(description = "初始化文件上傳",logType = LogType.BUSINESS_OPERATION,recordParams = true,recordResult = true)@PreAuthorize("hasAuthority('system:file:upload')")public Result<FileUploadInitResponse> initFileUpload(@Valid @RequestBody FileUploadInitRequest request,@AuthenticationPrincipal CustomUserDetails customUserDetails) {log.info("用戶 {} 初始化文件上傳: {}", customUserDetails.getUsername(), request.getFileName());FileUploadInitResponse response = fileUploadService.initFileUpload(request, customUserDetails.getId());return Result.success(response);}

?

五、重新定義文件上傳的可靠性邊界

一個文件上傳系統的實現,更是對現代文件傳輸需求的深度思考。通過分塊上傳、批量處理、全棧監控和智能去重等技術手段,展示了如何構建一個真正可靠、可觀測、可擴展的文件上傳系統。

關鍵技術亮點匯接:

  • 分塊上傳:5MB默認分塊,支持并發上傳和斷點續傳
  • 批量處理:多文件同時上傳,獨立狀態管理
  • 智能去重:MD5哈希秒傳機制
  • 全棧監控:Prometheus + Grafana + AlertManager完整監控棧
  • AOP控控:無侵入式性能追蹤
  • 容器化部署:Docker Compose一鍵啟動
  • Range請求:流媒體預覽支持
  • 企業安全:JWT認證和權限控制

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87962.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87962.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87962.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

系統學習Python——并發模型和異步編程:進程、線程和GIL

分類目錄&#xff1a;《系統學習Python》總目錄 在文章《并發模型和異步編程&#xff1a;基礎知識》我們簡單介紹了Python中的進程、線程和協程。本文就著重介紹Python中的進程、線程和GIL的關系。 Python解釋器的每個實例都是一個進程。使用multiprocessing或concurrent.futu…

【playwright篇】教程(十七)[html元素知識]

1 html中&#xff0c;button元素中的aria-describedby"tooltip-r1k"屬性&#xff0c;主要用來做什么&#xff1f;在 HTML 中&#xff0c;button 元素中的 aria-describedby"tooltip-r1k" 屬性主要用于提升網頁的可訪問性&#xff08;Accessibility&#xf…

Python: 正則表達式

正則表達式是處理文本數據的強大工具&#xff0c;Python通過re模塊提供了完整的正則表達式功能。本文將詳細介紹Python正則表達式的使用方法&#xff0c;包括基礎語法、高級技巧和re模塊API的詳細解析。一、正則表達式基礎1.1 什么是正則表達式正則表達式(Regular Expression)是…

pytest合并allure報告解決方案

背景 在執行自動化測試的過程中&#xff0c;為了實現自動化的高通過率&#xff0c;可能會反復的重試&#xff0c;直至大多數甚至全部用例執行通過&#xff0c;以此來需要人為分析的用例量&#xff0c;減少人力投入&#xff0c;提高執行效率&#xff1b; 在用例少或者資源消耗小…

Pr插件圖文安裝教程

Pr插件圖文安裝教程 Adobe Premiere Pro&#xff0c;簡稱Pr&#xff0c;是由Adobe公司開發的一款視頻編輯軟件。Adobe Premiere有較好的兼容性&#xff0c;且可以與Adobe公司推出的其他軟件相互協作。這款軟件廣泛應用于廣告制作和電視節目制作中&#xff0c;是視頻編輯愛好者…

[netty5: HttpObjectEncoder HttpObjectDecoder]-源碼解析

在閱讀該篇文章之前&#xff0c;推薦先閱讀以下內容&#xff1a; [netty5: HttpObject]-源碼解析[netty5: MessageToMessageCodec & MessageToMessageEncoder & MessageToMessageDecoder]-源碼分析[netty5: ByteToMessageCodec & MessageToByteEncoder & Byte…

uniapp的navigator跳轉功能

接下來&#xff0c;我將圍繞一個常見的電商小程序來構建一系列連貫的使用場景。在這個過程中&#xff0c;我們將把 <navigator> 組件的所有關鍵屬性和方法都串聯起來&#xff0c;并詳細解釋它們在每個環節所扮演的角色和作用。 核心場景&#xff1a;構建一個電商小程序的…

v-for的用法及案例

目錄 一.v-for的用法 1.舉例1 2.舉例2 二.購物車案例 1.代碼 2.存在的問題&#xff1a;復選框錯位 3.解決方案&#xff1a; 賦值給key屬性一個唯一的值 一.v-for的用法 1.舉例1 <template><view><view v-for"(item,index) in 10" :key"…

BigQuery對象引用(ObjectRef)全面指南:一站式整合結構化與非結構化多模態數據分析

引言 企業需要同時管理有組織表格中的結構化數據&#xff0c;以及日益增長的非結構化數據&#xff08;如圖片、音頻和文檔&#xff09;。傳統上&#xff0c;聯合分析這些多樣化數據類型非常復雜&#xff0c;通常需要使用不同的工具。非結構化媒體通常需要導出到專門的服務進行…

【開源品鑒】FRP源碼閱讀

frp 是一款高性能的反向代理應用&#xff0c;專注于內網穿透&#xff0c;支持多種協議和 P2P 通信功能&#xff0c;目前在 GitHub 上已有 80k 的 star。本文將深入探討其源碼&#xff0c;揭示其背后的實現原理。1. 前言 frp 是一款高性能的反向代理應用&#xff0c;專注于內網…

day048-系統負載高排查流程與前后端分離項目

文章目錄 0. 老男孩思想1. 系統負載高排查流程1.1 進程/線程相關命令1.1.1 jps1.1.2 jstack1.1.3 jmap1.1.4 top -Hp pid 1.2 排查流程圖 2. 前后端分離項目2.1 項目說明2.2 負載均衡2.3 數據庫配置2.3.1 安裝數據庫服務2.3.2 配置數據庫環境 2.4 后端配置2.5 四層負載均衡配置…

Spring Boot 牽手EasyExcel:解鎖高效數據處理姿勢

引言 在日常的 Java 開發中&#xff0c;處理 Excel 文件是一個極為常見的需求。無論是數據的導入導出&#xff0c;還是報表的生成&#xff0c;Excel 都扮演著重要的角色。例如&#xff0c;在企業的財務管理系統中&#xff0c;需要將每月的財務數據導出為 Excel 報表&#xff0…

【ARM AMBA AXI 入門 21 -- AXI partial 訪問和 narrow 訪問的區別】

文章目錄 Overview一、定義區別二、AXI 信號層面對比三、舉例說明示例一:Partial Access示例二:Narrow Access四、硬件/系統處理角度五、AXI 總線接口信號舉例對比Partial Write 事務:Narrow Write 事務(32-bit Master on 64-bit Bus):六、總結對比表七,軟件判斷判斷 Pa…

使用Ideal創建一個spring boot的helloWorld項目

說明&#xff1a;本篇將介紹如何使用Ideal2024.2.1去創建一個spring boot的helloWorld項目&#xff0c;本篇將包含創建的詳細步驟以及spring boot項目的目錄結構說明&#xff0c;創建過程中的選項說明等。詳細步驟如下&#xff1a;第一步&#xff1a;點擊文件——新建——項目&…

國內Ubuntu訪問不了github等外網

各位小伙伴們&#xff0c;大家好呀。 大家是不是經常遇到訪問不了外網的情況呀。 在Ubuntu中可以這樣做。 訪問這個網站網站測速-Ping檢測-Trace查詢-Dig查詢-路由跟蹤查詢-tools.ipip.net&#xff0c; 對于github.com&#xff0c;在這個網站輸入github.com&#xff0c;會返…

PDF轉換工具,即開即用

在辦公室里&#xff0c;這句話被反復驗證。每天面對成堆的Word和Excel文件&#xff0c;將它們轉換成PDF格式是常有的事。可之前用過的工具&#xff0c;不是一次只能轉一個&#xff0c;就是操作繁瑣得讓人頭疼。記得有次趕項目&#xff0c;需要把二十多個文檔轉成PDF&#xff0c…

2. 你可以說一下 http 版本的發展過程嗎

你可以說一下 http 版本的發展過程嗎 總結&#xff1a;0.9&#xff1a;只能發送 get&#xff0c;無狀態。1.0&#xff1a;新增 post&#xff0c;請求頭&#xff0c;狀態碼&#xff0c;cookie。1.1&#xff1a;新增 put/delete/options/patch&#xff0c;keep-alive&#xff0c…

04-Linux驅動模塊的自動加載

概述 上一節&#xff0c;我們講述了Linux驅動開發的基本的模塊代碼編寫和手動執行模塊加載的操作&#xff0c; 這一節&#xff0c;我們講述嵌入式設備上使用Sysvint引導方式下如何開機自動加載模塊的步驟。感興趣的同學看下使用systemd引導方式的開啟自動加載模塊的步驟 操作…

【牛客算法】游游的整數切割

文章目錄 一、題目介紹1.1 題目鏈接1.2 題目描述1.3 輸入描述1.4 輸出描述1.5 示例二、解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、解法實現3.1 解法一:基礎遍歷法3.1.1 初級版本分析3.2 解法二:奇偶預統計法(推薦)3.2.1 優化版本分析四、總結與拓展4.1 關…

筆記本電腦忽亮忽暗問題

關于筆記本電腦忽亮忽暗的問題這個問題困擾了我大半年&#xff0c;最后忽然找到解決方法了---主要的話有三種可能性1.關閉顯示器自動調亮的功能2.關閉節能模式自動調亮功能3.調整顯卡的功率&#xff0c;關閉自動調亮功能一開始一直都是嘗試的第一種方法&#xff0c;沒解決。。。…