Просмотр исходного кода

Respect cancellation token/HTTP request aborts correctly in `SymlinkFollowingPhysicalFileResultExecutor` (#13033)

Akaanksh Raj 6 месяцев назад
Родитель
Сommit
293e0f5faf

+ 15 - 5
Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs

@@ -101,7 +101,7 @@ namespace Jellyfin.Server.Infrastructure
                 count: null);
         }
 
-        private async Task SendFileAsync(string filePath, HttpResponse response, long offset, long? count)
+        private async Task SendFileAsync(string filePath, HttpResponse response, long offset, long? count, CancellationToken cancellationToken = default)
         {
             var fileInfo = GetFileInfo(filePath);
             if (offset < 0 || offset > fileInfo.Length)
@@ -118,6 +118,9 @@ namespace Jellyfin.Server.Infrastructure
             // Copied from SendFileFallback.SendFileAsync
             const int BufferSize = 1024 * 16;
 
+            var useRequestAborted = !cancellationToken.CanBeCanceled;
+            var localCancel = useRequestAborted ? response.HttpContext.RequestAborted : cancellationToken;
+
             var fileStream = new FileStream(
                 filePath,
                 FileMode.Open,
@@ -127,10 +130,17 @@ namespace Jellyfin.Server.Infrastructure
                 options: FileOptions.Asynchronous | FileOptions.SequentialScan);
             await using (fileStream.ConfigureAwait(false))
             {
-                fileStream.Seek(offset, SeekOrigin.Begin);
-                await StreamCopyOperation
-                    .CopyToAsync(fileStream, response.Body, count, BufferSize, CancellationToken.None)
-                    .ConfigureAwait(true);
+                try
+                {
+                    localCancel.ThrowIfCancellationRequested();
+                    fileStream.Seek(offset, SeekOrigin.Begin);
+                    await StreamCopyOperation
+                        .CopyToAsync(fileStream, response.Body, count, BufferSize, localCancel)
+                        .ConfigureAwait(true);
+                }
+                catch (OperationCanceledException) when (useRequestAborted)
+                {
+                }
             }
         }