ChandimaPrabath commited on
Commit
3060540
·
verified ·
2 Parent(s): e747174 c5d7048

Merge branch #Hans-Den/instance1' into 'Hans-Den/instance5'

Browse files
Files changed (1) hide show
  1. app.py +41 -22
app.py CHANGED
@@ -1,4 +1,4 @@
1
- from fastapi.responses import JSONResponse, FileResponse, Response
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi import FastAPI, HTTPException, Request
4
  import mimetypes
@@ -32,9 +32,8 @@ app.add_middleware(
32
  allow_headers=["*"],
33
  )
34
 
35
-
36
  async def serve_video(file_path: str, request: Request):
37
- """Serve video file with support for range requests."""
38
  if not os.path.isfile(file_path):
39
  raise HTTPException(status_code=404, detail="Video file not found")
40
 
@@ -46,48 +45,68 @@ async def serve_video(file_path: str, request: Request):
46
  if mime_type is None:
47
  mime_type = 'application/octet-stream' # Fallback MIME type
48
 
 
 
 
 
 
 
49
  if range_header:
50
- # Simple parsing for range values
51
  range_specifier = range_header.replace('bytes=', '').strip()
52
  start, end = (None, None)
53
-
54
  if '-' in range_specifier:
55
  start_str, end_str = range_specifier.split('-')
56
  start = int(start_str)
57
  end = int(end_str) if end_str else file_size - 1
58
 
59
- # Validate range
60
  if start is None or start >= file_size or (end is not None and end >= file_size) or (end is not None and start > end):
61
  raise HTTPException(status_code=416, detail="Requested range not satisfiable")
62
 
 
 
63
  headers = {
64
- 'Content-Range': f'bytes {start}-{end or file_size - 1}/{file_size}',
65
  'Accept-Ranges': 'bytes',
66
- 'Content-Length': str((end - start + 1) if end is not None else file_size - start),
67
  'Content-Type': mime_type
68
  }
 
69
 
70
  async with aiofiles.open(file_path, 'rb') as f:
71
  await f.seek(start)
72
- chunk_size = 8388608 # Read in 8MB chunks
73
  data = bytearray()
74
-
75
- while start <= (end or file_size - 1):
76
- remaining = (end or file_size - 1) - start + 1
77
  read_size = min(chunk_size, remaining)
78
  chunk = await f.read(read_size)
79
-
80
- if not chunk: # EOF
81
  break
82
-
83
  data.extend(chunk)
84
- start += read_size
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- return Response(content=bytes(data), status_code=206, headers=headers) # Convert bytearray to bytes
87
-
88
- # Fallback for serving the whole file if no range requested
89
- return FileResponse(file_path, media_type=mime_type)
 
 
90
 
 
91
 
92
  @app.get("/")
93
  async def index():
@@ -95,7 +114,7 @@ async def index():
95
 
96
  @app.get("/api/get/report")
97
  async def get_report():
98
- report=instance.compile_report()
99
  return JSONResponse(report)
100
 
101
  @app.get('/api/get/tv/store')
@@ -105,7 +124,7 @@ async def get_tv_store_api():
105
 
106
  @app.get('/api/get/film/store')
107
  async def get_film_store_api():
108
- """Endpoint to get the TV store JSON."""
109
  return JSONResponse(instance.FILM_STORE)
110
 
111
  @app.get("/api/get/film/{title}")
 
1
+ from fastapi.responses import JSONResponse, StreamingResponse, Response
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi import FastAPI, HTTPException, Request
4
  import mimetypes
 
32
  allow_headers=["*"],
33
  )
34
 
 
35
  async def serve_video(file_path: str, request: Request):
36
+ """Serve video file with support for range requests and proper CORS headers."""
37
  if not os.path.isfile(file_path):
38
  raise HTTPException(status_code=404, detail="Video file not found")
39
 
 
45
  if mime_type is None:
46
  mime_type = 'application/octet-stream' # Fallback MIME type
47
 
48
+ # CORS headers to attach to all responses
49
+ cors_headers = {
50
+ 'Access-Control-Allow-Origin': '*',
51
+ 'Access-Control-Expose-Headers': 'Content-Length, Content-Range'
52
+ }
53
+
54
  if range_header:
55
+ # Parse range header (e.g., "bytes=START-END")
56
  range_specifier = range_header.replace('bytes=', '').strip()
57
  start, end = (None, None)
 
58
  if '-' in range_specifier:
59
  start_str, end_str = range_specifier.split('-')
60
  start = int(start_str)
61
  end = int(end_str) if end_str else file_size - 1
62
 
63
+ # Validate the range values
64
  if start is None or start >= file_size or (end is not None and end >= file_size) or (end is not None and start > end):
65
  raise HTTPException(status_code=416, detail="Requested range not satisfiable")
66
 
67
+ # Calculate content length and prepare headers
68
+ content_length = (end - start + 1) if end is not None else file_size - start
69
  headers = {
70
+ 'Content-Range': f'bytes {start}-{end}/{file_size}',
71
  'Accept-Ranges': 'bytes',
72
+ 'Content-Length': str(content_length),
73
  'Content-Type': mime_type
74
  }
75
+ headers.update(cors_headers)
76
 
77
  async with aiofiles.open(file_path, 'rb') as f:
78
  await f.seek(start)
79
+ chunk_size = 8 * 1024 * 1024 # 8 MB
80
  data = bytearray()
81
+ current = start
82
+ while current <= end:
83
+ remaining = end - current + 1
84
  read_size = min(chunk_size, remaining)
85
  chunk = await f.read(read_size)
86
+ if not chunk:
 
87
  break
 
88
  data.extend(chunk)
89
+ current += len(chunk)
90
+
91
+ return Response(content=bytes(data), status_code=206, headers=headers)
92
+ else:
93
+ # Fallback: Stream the entire file using StreamingResponse with proper headers
94
+ def iterfile():
95
+ with open(file_path, 'rb') as f:
96
+ while True:
97
+ chunk = f.read(8192)
98
+ if not chunk:
99
+ break
100
+ yield chunk
101
 
102
+ headers = {
103
+ 'Content-Length': str(file_size),
104
+ 'Accept-Ranges': 'bytes',
105
+ 'Content-Type': mime_type,
106
+ }
107
+ headers.update(cors_headers)
108
 
109
+ return StreamingResponse(iterfile(), media_type=mime_type, headers=headers)
110
 
111
  @app.get("/")
112
  async def index():
 
114
 
115
  @app.get("/api/get/report")
116
  async def get_report():
117
+ report = instance.compile_report()
118
  return JSONResponse(report)
119
 
120
  @app.get('/api/get/tv/store')
 
124
 
125
  @app.get('/api/get/film/store')
126
  async def get_film_store_api():
127
+ """Endpoint to get the film store JSON."""
128
  return JSONResponse(instance.FILM_STORE)
129
 
130
  @app.get("/api/get/film/{title}")