SpringMVC流式傳輸媒體數(shù)據(jù)的方法
借助Spring的ResourceHttpRequestHandler可以實(shí)現(xiàn)媒體數(shù)據(jù)的傳輸,比如在線播放視頻、預(yù)覽圖片等。
目前已知Spring Boot傳輸視頻流的方法
- 讀取整個(gè)視頻文件,然后把文件流寫入HttpServletResponse的OutputStream。
(此方法可行,但是需要消耗較多的服務(wù)器資源,且客戶端需要下載整個(gè)視頻才能播放) - 使用HTTP的Range實(shí)現(xiàn)分片加載,但是需要手動(dòng)實(shí)現(xiàn),比較麻煩。
- 使用Spring自帶的ResourceHttpRequestHandler是最佳實(shí)踐。
思路
ResourceHttpRequestHandler是Spring Boot用于加載靜態(tài)資源的一個(gè)類,默認(rèn)用于從"classpath:/static"等目錄讀取靜態(tài)資源,以便前端訪問(wèn)。我們可以繼承它自定義一個(gè)實(shí)現(xiàn)。
使用方法
在項(xiàng)目的config包(推薦)繼承ResourceHttpRequestHandler并重寫getResource方法,使其返回所需要呈現(xiàn)給前端的資源(org.springframework.core.io.Resource)
package com.example.server.config;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.util.List;
@Component
public class CustomResourceHttpRequestHandler extends ResourceHttpRequestHandler {
private Resource resource;
@Override
protected Resource getResource(@NonNull HttpServletRequest request) {
return this.resource;
}
public void setResource(Path filePath) throws MalformedURLException {
this.resource = new UrlResource(filePath.toUri());
setLocations(List.of(this.resource));
}
}控制層注入CustomResourceHttpRequestHandler,并向setResource方法傳入文件路徑(java.nio.file.Path),設(shè)置請(qǐng)求頭,最后讓customResourceHttpRequestHandler處理請(qǐng)求。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.file.Path;
import java.nio.file.Paths;
@Controller
@RequestMapping("/files")
public class FileController {
@Autowired
private CustomResourceHttpRequestHandler resourceHttpRequestHandler;
@GetMapping("/{filename}")
public ResponseEntity<?> getFile(@PathVariable String filename, HttpServletRequest request, HttpServletResponse response) {
try {
// 解析文件路徑
Path filePath = Paths.get("D:/StorageService").resolve(filename).normalize();
// 檢查文件是否存在
if (!filePath.toFile().exists()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
// 設(shè)置資源路徑
resourceHttpRequestHandler.setResource(filePath);
// 設(shè)置響應(yīng)頭,inline 會(huì)在瀏覽器中顯示或播放文件
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"");
// 讓 CustomResourceHttpRequestHandler 處理請(qǐng)求
resourceHttpRequestHandler.handleRequest(request, response);
return new ResponseEntity<>(HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}注意點(diǎn)
控制層返回值需要ResponseEntity類型(org.springframework.http.ResponseEntity),且try-catch不能省略,否則可能會(huì)不斷拋出異常(AsyncRequestNotUsableException和IOException)但不影響正常使用。
其他方案
如果有條件也可以使用MinIO,或者視頻云點(diǎn)播VOD。他們提供了現(xiàn)成的解決方案,通過(guò)調(diào)用API可以獲取視頻等文件的直鏈。
參考資料
springboot+vue播放視頻流(無(wú)需下載視頻,可以拖動(dòng)進(jìn)度、倍速播放)
到此這篇關(guān)于java的文章就介紹到這了,更多相關(guān)java內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中新建一個(gè)文件、目錄及路徑操作實(shí)例
這篇文章主要給大家介紹了關(guān)于Java中新建一個(gè)文件、目錄及路徑操作的相關(guān)資料,新建文件、目錄及路徑是我們?nèi)粘i_(kāi)發(fā)中經(jīng)常會(huì)遇到的一個(gè)需求,本文通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
java如何通過(guò)FileOutputStream字節(jié)流向文件中寫數(shù)據(jù)
這篇文章主要介紹了java如何通過(guò)FileOutputStream字節(jié)流向文件中寫數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Java中正則表達(dá)式匹配過(guò)程實(shí)例詳解
正則匹配即是在給定字符串中查找符合正則表達(dá)式的字符,下面這篇文章主要給大家介紹了關(guān)于Java中正則表達(dá)式匹配過(guò)程的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
Java利用Geotools從DEM數(shù)據(jù)中讀取指定位置的高程信息全過(guò)程
Geotools作為一款功能強(qiáng)大且開(kāi)源的地理工具庫(kù),為地理數(shù)據(jù)的處理和分析提供了豐富的類庫(kù)和便捷的接口,能夠很好地滿足從DEM數(shù)據(jù)中讀取高程信息這一實(shí)戰(zhàn)需求,本文將深入講解如何利用Geotools從獲取DEM數(shù)據(jù)到成功讀取指定位置高程信息的全過(guò)程,需要的朋友可以參考下2025-03-03
SpringSecurity OAuth2單點(diǎn)登錄和登出的實(shí)現(xiàn)
本文主要介紹了SpringSecurity OAuth2單點(diǎn)登錄和登出的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
springboot項(xiàng)目打包發(fā)布部署的過(guò)程及jar和war的區(qū)別
Spring Boot使用了內(nèi)嵌容器,因此它的部署方式也變得非常簡(jiǎn)單靈活,可以將Spring Boot項(xiàng)目打包成JAR包來(lái)獨(dú)立運(yùn)行,Spring Boot項(xiàng)目既可以生成WAR包發(fā)布,也可以生成JAR包發(fā)布,那么它們有什么區(qū)別呢2022-11-11

