diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs index e5e8ab35e..61371b962 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs @@ -69,9 +69,10 @@ public async Task DownloadResource(string filePath, string fileNa } var file = await this.fileService.DownloadFileAsync(filePath, fileName); + if (file != null) { - return this.File(file.Content, file.ContentType, fileName); + return !string.IsNullOrEmpty(file.DownloadUrl) ? this.Redirect(file.DownloadUrl) : this.File(file.Content, file.ContentType, fileName); } else { @@ -106,7 +107,8 @@ public async Task DownloadResourceAndRecordActivity(int resourceV ActivityStatus = ActivityStatusEnum.Completed, }; await this.activityService.CreateResourceActivityAsync(activity); - return this.File(file.Content, file.ContentType, fileName); + + return !string.IsNullOrEmpty(file.DownloadUrl) ? this.Redirect(file.DownloadUrl) : this.File(file.Content, file.ContentType, fileName); } else { diff --git a/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs b/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs index 8036e9320..1a4d76679 100644 --- a/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs +++ b/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs @@ -21,5 +21,10 @@ public class FileDownloadResponse /// Gets or sets the ContentType. /// public long ContentLength { get; set; } + + /// + /// Gets or sets when downloading large files, a SAS URL is returned so the client can download directly from Azure Files. + /// + public string DownloadUrl { get; set; } } } \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Services/FileService.cs b/LearningHub.Nhs.WebUI/Services/FileService.cs index e0d19d7f2..0f2878c92 100644 --- a/LearningHub.Nhs.WebUI/Services/FileService.cs +++ b/LearningHub.Nhs.WebUI/Services/FileService.cs @@ -1,17 +1,13 @@ namespace LearningHub.Nhs.WebUI.Services { using System; - using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; - using System.Threading; using System.Threading.Tasks; - using System.Threading.Tasks.Dataflow; - using Azure; - using Azure.Storage; using Azure.Storage.Files.Shares; using Azure.Storage.Files.Shares.Models; + using Azure.Storage.Sas; using LearningHub.Nhs.Models.Resource; using LearningHub.Nhs.WebUI.Configuration; using LearningHub.Nhs.WebUI.Interfaces; @@ -145,26 +141,19 @@ public async Task DownloadFileAsync(string filePath, strin try { - if (fileSize <= 900 * 1024 * 1024) + var response = new FileDownloadResponse { - // Directly download the entire file as a stream - var response = await file.DownloadAsync(); - return new FileDownloadResponse - { - Content = response.Value.Content, - ContentType = properties.Value.ContentType, - ContentLength = fileSize, - }; - } - else + ContentType = properties.Value.ContentType, + ContentLength = fileSize, + Content = await file.OpenReadAsync(), + }; + + if (fileSize >= 999 * 1024 * 1024) { - return new FileDownloadResponse - { - Content = await file.OpenReadAsync(), - ContentType = properties.Value.ContentType, - ContentLength = fileSize, - }; + response.DownloadUrl = this.GenerateSasUriForFile(file); } + + return response; } catch (Exception ex) { @@ -460,5 +449,23 @@ private async Task FindFileAsync(string filePath, string fileNa return null; } + + private string GenerateSasUriForFile(ShareFileClient fileClient) + { + if (fileClient.CanGenerateSasUri) + { + ShareSasBuilder sasBuilder = new ShareSasBuilder(ShareFileSasPermissions.Read, DateTimeOffset.UtcNow.AddMinutes(20)) + { + Protocol = SasProtocol.Https, + }; + + Uri sasUri = fileClient.GenerateSasUri(sasBuilder); + return sasUri.ToString(); + } + else + { + throw new InvalidOperationException("Unable to generate SAS URI for the file."); + } + } } } \ No newline at end of file