66using Newtonsoft . Json . Serialization ;
77
88using Syncfusion . Blazor . FileManager ;
9- using Syncfusion . Blazor . Inputs ;
109using Syncfusion . EJ2 . FileManager . Base ;
1110using Syncfusion . EJ2 . FileManager . PhysicalFileProvider ;
12- using Syncfusion . EJ2 . Notifications ;
13- using System ;
14- using System . Collections . Generic ;
15- using System . IO ;
1611using System . IO . Compression ;
17- using System . Linq ;
1812using System . Net ;
19- using System . Net . Http . Headers ;
20- using System . Runtime . Serialization . Formatters . Binary ;
2113using System . Web ;
22- using System . Xml . Linq ;
2314using TelegramDownloader . Data ;
2415using TelegramDownloader . Data . db ;
2516using TelegramDownloader . Models ;
@@ -37,12 +28,15 @@ public class FileController : ControllerBase
3728 public PhysicalFileProvider operation ;
3829 public string basePath ;
3930 string root = FileService . RELATIVELOCALDIR ;
31+
32+ private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim ( 1 ) ;
4033 IDbService _db { get ; set ; }
4134 ITelegramService _ts { get ; set ; }
4235 IFileService _fs { get ; set ; }
4336 TransactionInfoService _tis { get ; set ; }
37+ private ILogger < IFileService > _logger { get ; set ; }
4438
45- public FileController ( IDbService db , ITelegramService ts , IFileService fs , TransactionInfoService tis )
39+ public FileController ( IDbService db , ITelegramService ts , IFileService fs , TransactionInfoService tis , ILogger < IFileService > logger )
4640 {
4741 this . basePath = Environment . CurrentDirectory ;
4842 if ( ! System . IO . Directory . Exists ( Path . Combine ( basePath , root ) ) )
@@ -53,6 +47,7 @@ public FileController(IDbService db, ITelegramService ts, IFileService fs, Trans
5347 _ts = ts ;
5448 _db = db ;
5549 _tis = tis ;
50+ _logger = logger ;
5651
5752 this . operation = new PhysicalFileProvider ( ) ;
5853 this . operation . RootFolder ( Path . Combine ( basePath , root ) ) ;
@@ -248,9 +243,21 @@ public async Task<IActionResult> GetFile(string id, string? idChannel, string? i
248243 TL . Message idM = await _ts . getMessageFile ( idChannel , Convert . ToInt32 ( idFile ) ) ;
249244 ChatMessages cm = new ChatMessages ( ) ;
250245 cm . message = idM ;
251- file = new FileStream ( System . IO . Path . Combine ( FileService . TEMPDIR , "_temp" , $ "{ idChannel } -{ idFile } -{ id } ") , FileMode . Create , FileAccess . ReadWrite ) ;
246+ string filePath = System . IO . Path . Combine ( FileService . TEMPDIR , "_temp" , $ "{ idChannel } -{ idFile } -{ id } ") ;
247+ file = new FileStream ( filePath , FileMode . Create , FileAccess . ReadWrite ) ;
252248 DownloadModel dm = new DownloadModel ( ) ;
253249 dm . tis = _tis ;
250+ dm . startDate = DateTime . Now ;
251+ dm . path = filePath ;
252+ if ( cm . message is Message msgBase )
253+ {
254+ if ( msgBase . media is MessageMediaDocument mediaDoc &&
255+ mediaDoc . document is TL . Document doc )
256+ {
257+ dm . _size = doc . size ;
258+ dm . name = doc . Filename ;
259+ }
260+ }
254261 dm . channelName = _ts . getChatName ( Convert . ToInt64 ( idChannel ) ) ;
255262 _tis . addToDownloadList ( dm ) ;
256263 await _ts . DownloadFileAndReturn ( cm , file , model : dm ) ;
@@ -267,6 +274,100 @@ public async Task<IActionResult> GetFile(string id, string? idChannel, string? i
267274 } ;
268275 }
269276
277+ [ Route ( "GetFileByTfmIdNow/{id}" ) ]
278+ public async Task < IActionResult > GetFileByTfmIdNow ( string id , [ FromQuery ] string idChannel , [ FromQuery ] string idFile )
279+ {
280+ var fileName = id ;
281+ var mimeType = FileService . getMimeType ( id . Split ( "." ) . Last ( ) ) ;
282+ var dbFile = await _fs . getItemById ( idChannel , idFile ) ;
283+ if ( dbFile == null )
284+ {
285+ return new ObjectResult ( "" ) { StatusCode = ( int ) HttpStatusCode . NotFound } ;
286+ }
287+ var file = _fs . ExistFileIntempFolder ( $ "{ idChannel } -{ dbFile . MessageId } -{ id } ") ;
288+ if ( file == null )
289+ {
290+ TL . Message idM = await _ts . getMessageFile ( idChannel , Convert . ToInt32 ( dbFile . MessageId ) ) ;
291+ ChatMessages cm = new ChatMessages ( ) ;
292+ cm . message = idM ;
293+ String filePath = System . IO . Path . Combine ( FileService . TEMPDIR , "_temp" , $ "{ idChannel } -{ idFile } -{ id } ") ;
294+ file = new FileStream ( filePath , FileMode . Create , FileAccess . ReadWrite ) ;
295+ DownloadModel dm = new DownloadModel ( ) ;
296+ dm . tis = _tis ;
297+ dm . startDate = DateTime . Now ;
298+ dm . path = filePath ;
299+ dm . name = dbFile . Name ;
300+ dm . _size = dbFile . Size ;
301+ dm . channelName = _ts . getChatName ( Convert . ToInt64 ( idChannel ) ) ;
302+ _tis . addToDownloadList ( dm ) ;
303+ await _ts . DownloadFileAndReturn ( cm , file , model : dm ) ;
304+ file . Position = 0 ;
305+ }
306+
307+ Response . Headers [ "Content-Disposition" ] = $ "inline; filename=\" { HttpUtility . UrlEncode ( fileName ) } \" ";
308+
309+ return new FileStreamResult ( file , mimeType ) ;
310+ }
311+
312+ [ Route ( "GetFileByTfmId/{id}" ) ]
313+ public async Task < IActionResult > GetFileByTfmId ( string id , [ FromQuery ] string idChannel , [ FromQuery ] string idFile )
314+ {
315+ var fileName = id ;
316+ var mimeType = FileService . getMimeType ( id . Split ( "." ) . Last ( ) ) ;
317+ var dbFile = await _fs . getItemById ( idChannel , idFile ) ;
318+ if ( dbFile == null )
319+ {
320+ return new ObjectResult ( "" ) { StatusCode = ( int ) HttpStatusCode . NotFound } ;
321+ }
322+
323+ dbFile . Name = $ "{ idChannel } -{ ( dbFile . MessageId != null ? dbFile . MessageId . ToString ( ) : dbFile . Id ) } -{ id } ";
324+ String path = Path . Combine ( FileService . TEMPDIR , "_temp" ) ;
325+ String filePath = Path . Combine ( path , dbFile . Name ) ;
326+ var mutexState = semaphoreSlim . Wait ( 10000 ) ;
327+ FileStream ? file = null ;
328+ if ( ! mutexState )
329+ {
330+ _logger . LogWarning ( "Could not acquire download mutex in 10 seconds for file {fileName}" , dbFile . Name ) ;
331+ return StatusCode ( 500 , "Could not acquire download mutex in 10 seconds" ) ;
332+ }
333+
334+ file = _fs . ExistFileIntempFolder ( dbFile . Name ) ;
335+ var isFileDownloaded = _tis . isFileDownloaded ( filePath ) ;
336+ if ( ! isFileDownloaded )
337+ if ( ( file == null ) || ( file != null && file . Length < dbFile . Size ) )
338+ {
339+ _logger . LogWarning ( "Stream Downloading file {fileName}" , dbFile . Name ) ;
340+ await _fs . downloadFile ( idChannel , new List < Syncfusion . Blazor . FileManager . FileManagerDirectoryContent > { dbFile . toFileManagerContent ( ) } , path ) ;
341+ Thread . Sleep ( 4000 ) ;
342+ file = _fs . ExistFileIntempFolder ( dbFile . Name ) ;
343+ }
344+
345+ if ( mutexState )
346+ semaphoreSlim . Release ( ) ;
347+
348+ if ( file == null )
349+ {
350+ return NotFound ( ) ;
351+ }
352+
353+ Response . Headers [ "Content-Disposition" ] = $ "inline; filename=\" { HttpUtility . UrlEncode ( fileName ) } \" ";
354+
355+ try
356+ {
357+ return new FileStreamResult ( file , mimeType )
358+ {
359+ FileDownloadName = fileName ,
360+ EnableRangeProcessing = true
361+
362+ } ;
363+ }
364+ catch ( OperationCanceledException )
365+ {
366+ _logger . LogInformation ( "❌ El cliente cerró la conexión al descargar el archivo {fileName}." , fileName ) ;
367+ return StatusCode ( StatusCodes . Status499ClientClosedRequest ) ;
368+ }
369+ }
370+
270371 [ Route ( "strm" ) ]
271372 public async Task < IActionResult > GetStrm ( [ FromQuery ] string idChannel , [ FromQuery ] string path , [ FromQuery ] string host )
272373 {
@@ -288,7 +389,7 @@ public async Task<IActionResult> GetFileStream(string idChannel, string idFile,
288389
289390 var request = HttpContext . Request ;
290391 var rangeHeader = request . Headers [ "Range" ] . ToString ( ) ;
291- Console . WriteLine ( "range: ", rangeHeader ) ;
392+ _logger . LogDebug ( "GetFileStream - Range: {Range} ", rangeHeader ) ;
292393
293394 var file = await _fs . getItemById ( idChannel , idFile ) ;
294395 long totalLength = file . Size ;
@@ -319,7 +420,7 @@ public async Task<IActionResult> GetFileStream(string idChannel, string idFile,
319420
320421 if ( from >= totalPartialFileLength )
321422 {
322- Console . WriteLine ( "Take a file part: from: " + from + ", totalPartialFileLength: " + totalPartialFileLength ) ;
423+ _logger . LogDebug ( "Take a file part - From: {From}, TotalPartialFileLength: {TotalPartialFileLength}" , from , totalPartialFileLength ) ;
323424 int filePart = 0 ;
324425 while ( from >= totalPartialFileLength )
325426 {
@@ -339,7 +440,7 @@ public async Task<IActionResult> GetFileStream(string idChannel, string idFile,
339440 from = ( from / 524288 ) * 524288 ;
340441 }
341442
342- Console . WriteLine ( "Fom:" + from ) ;
443+ _logger . LogDebug ( "Stream position - From: {From}" , from ) ;
343444
344445 if ( to == 0 )
345446 if ( string . IsNullOrEmpty ( rangeHeader ) || from == 0 )
@@ -417,116 +518,13 @@ public async Task<IActionResult> GetFileStream(string idChannel, string idFile,
417518 }
418519 catch ( OperationCanceledException )
419520 {
420- Console . WriteLine ( "❌ El cliente cerró la conexión." ) ;
521+ _logger . LogInformation ( "Client closed connection during stream - File: {FileName}" , fileName ) ;
421522 }
422523
423524 return new EmptyResult ( ) ;
424525
425526 }
426527
427- [ Route ( "GetFileStream2/{idChannel}/{idFile}/{name}" ) ]
428- public async Task < IActionResult > GetFileStream2 ( string idChannel , string idFile , string name )
429- {
430- var fileName = name ;
431- var mimeType = FileService . getMimeType ( name . Split ( "." ) . Last ( ) ) ;
432-
433- var request = HttpContext . Request ;
434- var rangeHeader = request . Headers [ "Range" ] . ToString ( ) ;
435-
436- var file = await _fs . getItemById ( idChannel , idFile ) ;
437-
438- // HttpResponseMessage fullResponse = new HttpResponseMessage(HttpStatusCode.OK); // Request.CreateResponse(HttpStatusCode.OK);
439- TL . Message idM = await _ts . getMessageFile ( idChannel , file . MessageId ?? file . ListMessageId . FirstOrDefault ( ) ) ;
440- //byte[] data = await _ts.DownloadFileStream(idM, 0, 512);
441- //var stream = new MemoryStream(data);
442-
443- // Supón que puedes obtener el tamaño total del archivo remoto
444- long totalLength = ( await _fs . getItemById ( idChannel , idFile ) ) . Size ;
445-
446- long from = 0 ;
447- long initialFrom = 0 ;
448- long to = 0 ;
449-
450-
451-
452- if ( ! string . IsNullOrEmpty ( rangeHeader ) && rangeHeader . StartsWith ( "bytes=" ) )
453- {
454- var range = rangeHeader . Replace ( "bytes=" , "" ) . Split ( '-' ) ;
455- from = long . Parse ( range [ 0 ] ) ;
456- initialFrom = from ;
457- if ( range . Length > 1 && ! string . IsNullOrEmpty ( range [ 1 ] ) )
458- to = long . Parse ( range [ 1 ] ) ;
459- }
460-
461- if ( from > 0 )
462- {
463- from = ( from / 524288 ) * 524288 ;
464- }
465-
466- if ( to == 0 )
467- to = ( 25 * 524288 ) + from ;
468- else
469- to = ( ( to + 524288 ) / 524288 ) * 524288 ;
470-
471- if ( to > totalLength )
472- {
473- to = totalLength - 1 ;
474- }
475-
476- long length = to - from ;
477-
478- byte [ ] data = await _ts . DownloadFileStream ( idM , from , ( int ) length ) ;
479-
480- long skipedBytes = initialFrom - from ; // (data.Length + initialFrom) >= totalLength ? data.Length - (totalLength - initialFrom) : initialFrom - from;
481-
482- if ( skipedBytes < 0 ) skipedBytes = 0 ;
483-
484- if ( skipedBytes >= data . Length )
485- return StatusCode ( 500 , "No hay suficientes bytes en el bloque descargado" ) ;
486-
487- long dataLength = data . Length - skipedBytes ;
488- Response . ContentLength = ( dataLength + initialFrom ) >= totalLength ? totalLength - initialFrom : dataLength ;
489- // Response.StatusCode = (int)HttpStatusCode.PartialContent; // 206
490- Response . StatusCode = StatusCodes . Status206PartialContent ;
491- Response . ContentType = mimeType ;
492- Response . Headers . Add ( "Content-Range" , $ "bytes { initialFrom } -{ ( initialFrom + Response . ContentLength - 1 ) } /{ totalLength } ") ;
493- Response . Headers . Add ( "Accept-Ranges" , "bytes" ) ;
494-
495- if ( Request . Headers . ContainsKey ( "Range" ) )
496- {
497- Console . WriteLine ( "Range header recibido:" ) ;
498- Console . WriteLine ( Request . Headers [ "Range" ] ) ;
499- }
500-
501- foreach ( var header in Response . Headers )
502- {
503- Console . WriteLine ( $ "{ header . Key } : { header . Value } ") ;
504- }
505-
506-
507-
508-
509- var stream = new MemoryStream ( data , ( int ) skipedBytes , ( int ) Response . ContentLength ) ;
510-
511- Console . WriteLine ( "Real Data length: " + stream . Length ) ;
512-
513- Console . WriteLine ( "---------------------------------------------------" ) ;
514-
515- //return new FileStreamResult(stream, mimeType);
516- var cancellationToken = HttpContext . RequestAborted ;
517-
518- await stream . CopyToAsync ( Response . Body , 64 * 1024 , cancellationToken ) ;
519- await Response . Body . FlushAsync ( cancellationToken ) ;
520-
521- return new EmptyResult ( ) ;
522- // return File(stream, mimeType, enableRangeProcessing: false);
523- //return new FileStreamResult(stream, mimeType)
524- //{
525- // EnableRangeProcessing = false
526- //};
527-
528- }
529-
530528 [ Route ( "export/{id}" ) ]
531529 public async Task < IActionResult > ExportDatabase ( string id )
532530 {
0 commit comments