@@ -227,7 +227,7 @@ public async Task<IActionResult> StreamAudioByTfmId(string channelId, string tfm
227227 Directory . CreateDirectory ( tempPath ) ;
228228 }
229229
230- // Check if file is completely cached
230+ // Check if file is completely cached - serve directly with full Range support
231231 if ( System . IO . File . Exists ( filePath ) )
232232 {
233233 var fileInfo = new FileInfo ( filePath ) ;
@@ -238,17 +238,6 @@ public async Task<IActionResult> StreamAudioByTfmId(string channelId, string tfm
238238 }
239239 }
240240
241- // Start or get background download
242- var downloadInfo = await _progressiveDownload . StartOrGetDownloadAsync (
243- cacheFileName , channelId , dbFile , filePath ) ;
244-
245- // If download completed while we were waiting, serve the file
246- if ( downloadInfo . IsComplete )
247- {
248- _logger . LogDebug ( "Download completed, serving cached file: {FileName}" , name ) ;
249- return PhysicalFile ( filePath , mimeType , name , enableRangeProcessing : true ) ;
250- }
251-
252241 // Parse range header
253242 var rangeHeader = Request . Headers [ "Range" ] . ToString ( ) ;
254243 long from = 0 ;
@@ -266,17 +255,11 @@ public async Task<IActionResult> StreamAudioByTfmId(string channelId, string tfm
266255
267256 long totalLength = dbFile . Size ;
268257
269- // Check if requested range is available in local cache
270- var downloadedBytes = downloadInfo . DownloadedBytes ;
258+ // Check how much is already cached
259+ long cachedBytes = 0 ;
271260 if ( System . IO . File . Exists ( filePath ) )
272261 {
273- downloadedBytes = Math . Max ( downloadedBytes , new System . IO . FileInfo ( filePath ) . Length ) ;
274- }
275-
276- // If no range or range is within cached portion, serve from cache
277- if ( ! hasRange && downloadedBytes >= totalLength )
278- {
279- return PhysicalFile ( filePath , mimeType , name , enableRangeProcessing : true ) ;
262+ cachedBytes = new FileInfo ( filePath ) . Length ;
280263 }
281264
282265 // For initial request without Range, return first chunk as 206 with full size info
@@ -295,10 +278,10 @@ public async Task<IActionResult> StreamAudioByTfmId(string channelId, string tfm
295278 }
296279
297280 // Check if range is available locally
298- if ( from < downloadedBytes )
281+ if ( from < cachedBytes )
299282 {
300283 // Part or all of range is in cache
301- var availableEnd = Math . Min ( to , downloadedBytes - 1 ) ;
284+ var availableEnd = Math . Min ( to , cachedBytes - 1 ) ;
302285 var length = availableEnd - from + 1 ;
303286
304287 _logger . LogDebug ( "Serving from cache: bytes {From}-{To} of {Total}" , from , availableEnd , totalLength ) ;
@@ -783,98 +766,6 @@ public async Task<IActionResult> DownloadAudioComplete(string channelId, string
783766 // (balance between speed and not overwhelming Telegram API)
784767 private static readonly SemaphoreSlim _downloadSemaphoreSequential = new ( 3 ) ;
785768
786- /// <summary>
787- /// Stream file progressively for initial request (no Range header).
788- /// This ensures LibVLC receives Content-Length = full file size so it knows the duration.
789- /// The actual data is streamed as it becomes available from cache or Telegram.
790- /// </summary>
791- private async Task StreamProgressivelyAsync (
792- string channelId ,
793- BsonFileManagerModel dbFile ,
794- string filePath ,
795- long totalLength ,
796- ProgressiveDownloadInfo downloadInfo )
797- {
798- const int chunkSize = 524288 ; // 512KB chunks
799- long position = 0 ;
800-
801- try
802- {
803- while ( position < totalLength )
804- {
805- // Check how much is available in cache
806- long availableBytes = 0 ;
807- if ( System . IO . File . Exists ( filePath ) )
808- {
809- availableBytes = new FileInfo ( filePath ) . Length ;
810- }
811-
812- if ( position < availableBytes )
813- {
814- // Read from cache
815- var bytesToRead = ( int ) Math . Min ( chunkSize , availableBytes - position ) ;
816- using var fs = new FileStream ( filePath , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
817- fs . Seek ( position , SeekOrigin . Begin ) ;
818- var buffer = new byte [ bytesToRead ] ;
819- var read = await fs . ReadAsync ( buffer , 0 , bytesToRead ) ;
820- if ( read > 0 )
821- {
822- await Response . Body . WriteAsync ( buffer , 0 , read ) ;
823- await Response . Body . FlushAsync ( ) ;
824- position += read ;
825- }
826- }
827- else
828- {
829- // Need to get from Telegram
830- if ( ! dbFile . MessageId . HasValue )
831- {
832- _logger . LogError ( "File has no MessageId, cannot stream from Telegram" ) ;
833- break ;
834- }
835-
836- var message = await _ts . getMessageFile ( channelId , dbFile . MessageId . Value ) ;
837- if ( message == null )
838- {
839- _logger . LogError ( "Message not found in Telegram" ) ;
840- break ;
841- }
842-
843- // Align to 512KB boundary for Telegram
844- var alignedFrom = ( position / chunkSize ) * chunkSize ;
845- var downloadLength = Math . Min ( chunkSize * 4 , totalLength - alignedFrom ) ; // Download 2MB at a time
846-
847- var data = await _ts . DownloadFileStream ( message , alignedFrom , ( int ) downloadLength ) ;
848-
849- var skipBytes = position - alignedFrom ;
850- var bytesToWrite = ( int ) Math . Min ( data . Length - skipBytes , totalLength - position ) ;
851-
852- if ( bytesToWrite > 0 )
853- {
854- await Response . Body . WriteAsync ( data , ( int ) skipBytes , bytesToWrite ) ;
855- await Response . Body . FlushAsync ( ) ;
856- position += bytesToWrite ;
857- }
858- }
859-
860- // Check if client disconnected
861- if ( HttpContext . RequestAborted . IsCancellationRequested )
862- {
863- _logger . LogDebug ( "Client disconnected during progressive streaming" ) ;
864- break ;
865- }
866- }
867- }
868- catch ( OperationCanceledException )
869- {
870- _logger . LogDebug ( "Progressive streaming cancelled" ) ;
871- }
872- catch ( Exception ex )
873- {
874- _logger . LogError ( ex , "Error during progressive streaming at position {Position}" , position ) ;
875- }
876- }
877-
878769 private static string GetMimeType ( string extension )
879770 {
880771 return extension . ToLowerInvariant ( ) switch
0 commit comments