Skip to content

Commit 983991b

Browse files
author
Taois
committed
fix: 修复播放器解析 Content-Type 失败及 gzip 导致的数据长度不匹配问题
1 parent 75a424a commit 983991b

File tree

4 files changed

+60
-12
lines changed

4 files changed

+60
-12
lines changed

mediaProxy/custom_spider.jar

1.23 KB
Binary file not shown.

mediaProxy/custom_spider.jar.md5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c1c95fa9cde443c3bf94a50985c400bc
1+
dc6385947115895682a99865db0ca0db

mediaProxy/proxy.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ func (p *ProxyDownloadStruct) ProxyWorker(req *http.Request) {
277277
newHeader[name] = value
278278
}
279279
}
280+
newHeader["Accept-Encoding"] = []string{"identity"}
280281

281282
maxRetries := 5
282283
if startOffset < int64(1048576) || (p.EndOffset-startOffset)/p.EndOffset*1000 < 2 {
@@ -287,7 +288,7 @@ func (p *ProxyDownloadStruct) ProxyWorker(req *http.Request) {
287288
var err error
288289
for retry := 0; retry < maxRetries; retry++ {
289290
resp, err = base.RestyClient.
290-
SetTimeout(10*time.Second).
291+
SetTimeout(30*time.Second).
291292
SetRetryCount(1).
292293
SetCookieJar(p.CookieJar).
293294
R().
@@ -345,7 +346,12 @@ func (p *ProxyDownloadStruct) ProxyWorker(req *http.Request) {
345346

346347
// 接收数据
347348
if resp != nil {
348-
chunk.put(resp.Body())
349+
body := resp.Body()
350+
expectedLen := int(chunk.endOffset - chunk.startOffset + 1)
351+
if len(body) != expectedLen {
352+
logrus.Warnf("【警告】收到数据长度不匹配! 请求 range=%d-%d (预期 %d), 实际收到 %d bytes, Content-Range: %s", chunk.startOffset, chunk.endOffset, expectedLen, len(body), resp.Header().Get("Content-Range"))
353+
}
354+
chunk.put(body)
349355
} else {
350356
logrus.Debugf("Chunk range=%d-%d 无法获取数据,写入 nil 并停止调度新任务", chunk.startOffset, chunk.endOffset)
351357
chunk.put(nil) // 放入 nil 标记此 chunk 失败或结束
@@ -450,6 +456,8 @@ func handleGetMethod(w http.ResponseWriter, req *http.Request) {
450456
newHeader[name] = value
451457
}
452458
}
459+
// 强制要求服务器不进行 gzip 压缩,否则可能导致分片数据大小不匹配
460+
newHeader["Accept-Encoding"] = []string{"identity"}
453461

454462
// 移除错误的URL参数追加逻辑,因为这会破坏原始URL
455463
// 代理服务应该直接使用解码后的完整URL,而不是修改它
@@ -551,27 +559,30 @@ func handleGetMethod(w http.ResponseWriter, req *http.Request) {
551559
}
552560

553561
contentType := responseHeaders.Get("Content-Type")
554-
if contentType == "" {
555-
if strings.HasSuffix(fileName, ".webm") {
562+
if contentType == "" || contentType == "application/octet-stream" {
563+
urlLower := strings.ToLower(url)
564+
if strings.HasSuffix(fileName, ".webm") || strings.Contains(urlLower, "fext=webm") || strings.Contains(urlLower, ".webm") {
556565
contentType = "video/webm"
557-
} else if strings.HasSuffix(fileName, ".avi") {
566+
} else if strings.HasSuffix(fileName, ".avi") || strings.Contains(urlLower, "fext=avi") || strings.Contains(urlLower, ".avi") {
558567
contentType = "video/x-msvideo"
559-
} else if strings.HasSuffix(fileName, ".wmv") {
568+
} else if strings.HasSuffix(fileName, ".wmv") || strings.Contains(urlLower, "fext=wmv") || strings.Contains(urlLower, ".wmv") {
560569
contentType = "video/x-ms-wmv"
561-
} else if strings.HasSuffix(fileName, ".flv") {
570+
} else if strings.HasSuffix(fileName, ".flv") || strings.Contains(urlLower, "fext=flv") || strings.Contains(urlLower, ".flv") {
562571
contentType = "video/x-flv"
563-
} else if strings.HasSuffix(fileName, ".mov") {
572+
} else if strings.HasSuffix(fileName, ".mov") || strings.Contains(urlLower, "fext=mov") || strings.Contains(urlLower, ".mov") {
564573
contentType = "video/quicktime"
565-
} else if strings.HasSuffix(fileName, ".mkv") {
574+
} else if strings.HasSuffix(fileName, ".mkv") || strings.Contains(urlLower, "fext=mkv") || strings.Contains(urlLower, ".mkv") {
566575
contentType = "video/x-matroska"
567-
} else if strings.HasSuffix(fileName, ".ts") {
576+
} else if strings.HasSuffix(fileName, ".ts") || strings.Contains(urlLower, "fext=ts") || strings.Contains(urlLower, ".ts") {
568577
contentType = "video/mp2t"
569578
} else if strings.HasSuffix(fileName, ".mpeg") || strings.HasSuffix(fileName, ".mpg") {
570579
contentType = "video/mpeg"
571580
} else if strings.HasSuffix(fileName, ".3gpp") || strings.HasSuffix(fileName, ".3gp") {
572581
contentType = "video/3gpp"
573-
} else if strings.HasSuffix(fileName, ".mp4") || strings.HasSuffix(fileName, ".m4s") {
582+
} else if strings.HasSuffix(fileName, ".mp4") || strings.HasSuffix(fileName, ".m4s") || strings.Contains(urlLower, "fext=mp4") || strings.Contains(urlLower, ".mp4") {
574583
contentType = "video/mp4"
584+
} else {
585+
contentType = "video/mp4" // 默认降级为 mp4,解决播放器无法识别 octet-stream 的问题
575586
}
576587
responseHeaders.Set("Content-Type", contentType)
577588
}
@@ -594,6 +605,7 @@ func handleGetMethod(w http.ResponseWriter, req *http.Request) {
594605
// const maxBufferSize = 1*1024 // 1KB
595606

596607
// 必须先写入 Header
608+
responseHeaders.Del("Transfer-Encoding")
597609
for key, values := range responseHeaders {
598610
if strings.EqualFold(strings.ToLower(key), "connection") || strings.EqualFold(strings.ToLower(key), "proxy-connection") {
599611
continue
@@ -746,6 +758,7 @@ func handleGetMethod(w http.ResponseWriter, req *http.Request) {
746758
responseHeaders.Set("Accept-Ranges", "bytes")
747759

748760
// 先设置响应头,再开始数据传输
761+
responseHeaders.Del("Transfer-Encoding") // 避免播放器因为存在 Chunked 而拒绝解析 Content-Length
749762
for key, values := range responseHeaders {
750763
if strings.EqualFold(strings.ToLower(key), "connection") || strings.EqualFold(strings.ToLower(key), "proxy-connection") {
751764
continue
@@ -844,6 +857,8 @@ func handleOtherMethod(w http.ResponseWriter, req *http.Request) {
844857
newHeader[name] = value
845858
}
846859
}
860+
// 强制要求服务器不进行 gzip 压缩
861+
newHeader["Accept-Encoding"] = []string{"identity"}
847862

848863
// 移除错误的URL参数追加逻辑,直接使用解码后的完整URL
849864

mediaProxy/test_data.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import requests
2+
import hashlib
3+
import time
4+
5+
url = "http://127.0.0.1:5575/proxy?thread=6&chunkSize=256&url=https%3A%2F%2Fvod3379-aliyun04-vip-lixian.xunlei.com%2Fdownload%2F%3Ffid%3DADEJ-U770pd-KUWVHluMvw*odhrgCuEOAAAAAM21Q7mBWcQ*gECXy9cFLFm3n9P1%26mid%3D666%26threshold%3D251%26tid%3D57DC1FDAB5CD06F7E7DD31B5B0F082B7%26srcid%3D0%26verno%3D2%26pk%3Dxdrive%26e%3D1774147633%26g%3DCDB543B98159C43E804097CBD7052C59B79FD3F5%26i%3D003109FD4EFBD2977F2945951E5B8CBF0FA8761A%26ui%3D888880000085116%26t%3D1%26hy%3D0%26ms%3D8243280%26th%3D824328%26pt%3D0%26f%3D249629408%26alt%3D0%26pks%3D654%26rts%3D%26us%3D0%26hspu%3D%26po%3D0%26css%3D661498228%26rsrc%3D102%26ctrsc%3D1%26mtp%3Dvideo_mp2t%26vb%3D2198215%26pr%3D300%26rg%3D0-82432800%26spr%3Dplaytrans%26clientid%3DXqp0kJBXWhwaTpB6%26projectid%3D2rvk4e3gkdnl7u1kl0k%26share_user_id%3D%26vc%3Dhevc%26source%3Dxdrive%26cliplugver%3D%26tras%3D1%26fileid%3DVOn_0MOi1VqQ2NkijYYEbyOgA1%26fext%3Dmp4%26userid%3D%26vip%3DFREE%26clientver%3D%26at%3DF935152B36F10D0252C04E3862B14CB2"
6+
7+
def get_md5(url_to_test):
8+
print(f"Downloading from {url_to_test}...")
9+
m = hashlib.md5()
10+
resp = requests.get(url_to_test, stream=True, headers={"Range": "bytes=0-5000000"}, verify=False)
11+
print("Status:", resp.status_code)
12+
print("Content-Length:", resp.headers.get("Content-Length"))
13+
downloaded = 0
14+
start = time.time()
15+
for chunk in resp.iter_content(chunk_size=1024*1024):
16+
if chunk:
17+
m.update(chunk)
18+
downloaded += len(chunk)
19+
print(f"Downloaded {downloaded} bytes in {time.time()-start:.2f}s")
20+
return m.hexdigest()
21+
22+
direct_url = "https://vod3379-aliyun04-vip-lixian.xunlei.com/download/?fid=ADEJ-U770pd-KUWVHluMvw*odhrgCuEOAAAAAM21Q7mBWcQ*gECXy9cFLFm3n9P1&mid=666&threshold=251&tid=57DC1FDAB5CD06F7E7DD31B5B0F082B7&srcid=0&verno=2&pk=xdrive&e=1774147633&g=CDB543B98159C43E804097CBD7052C59B79FD3F5&i=003109FD4EFBD2977F2945951E5B8CBF0FA8761A&ui=888880000085116&t=1&hy=0&ms=8243280&th=824328&pt=0&f=249629408&alt=0&pks=654&rts=&us=0&hspu=&po=0&css=661498228&rsrc=102&ctrsc=1&mtp=video_mp2t&vb=2198215&pr=300&rg=0-82432800&spr=playtrans&clientid=Xqp0kJBXWhwaTpB6&projectid=2rvk4e3gkdnl7u1kl0k&share_user_id=&vc=hevc&source=xdrive&cliplugver=&tras=1&fileid=VOn_0MOi1VqQ2NkijYYEbyOgA1&fext=mp4&userid=&vip=FREE&clientver=&at=F935152B36F10D0252C04E3862B14CB2"
23+
24+
md5_direct = get_md5(direct_url)
25+
print("Direct MD5:", md5_direct)
26+
27+
md5_proxy = get_md5(url)
28+
print("Proxy MD5:", md5_proxy)
29+
30+
if md5_direct == md5_proxy:
31+
print("SUCCESS: Data matches exactly!")
32+
else:
33+
print("ERROR: Data mismatch!")

0 commit comments

Comments
 (0)