Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions DotNet/Submission/Application/Services/BlobStorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,13 @@ public async Task UploadToExternalAsync(
await stream.WriteAsync(content, cancellationToken);
}

public async Task<IDictionary<string, byte[]>> DownloadFromExternalAsync(string payloadRootUri, CancellationToken cancellationToken = default)
private async Task<IDictionary<string, byte[]>> DownloadAsync(BlobContainerClient containerClient, string prefix, CancellationToken cancellationToken = default)
{
if (!HasExternalClient())
{
throw new InvalidOperationException("Not configured for external blob storage.");
}
IDictionary<string, byte[]> files = new Dictionary<string, byte[]>();
BlobUriBuilder uriBuilder = new(new Uri(payloadRootUri));
string prefix = ChangeBlobRoot(uriBuilder.BlobName);
await foreach (BlobItem blob in _externalContainerClient.GetBlobsAsync(prefix: prefix, cancellationToken: cancellationToken))
await foreach (BlobItem blob in containerClient.GetBlobsAsync(prefix: prefix, cancellationToken: cancellationToken))
{
_logger.LogDebug("Downloading: {}", blob.Name);
BlockBlobClient blobClient = _externalContainerClient.GetBlockBlobClient(blob.Name);
BlockBlobClient blobClient = containerClient.GetBlockBlobClient(blob.Name);
using Stream input = await blobClient.OpenReadAsync(cancellationToken: cancellationToken);
using MemoryStream output = new();
await input.CopyToAsync(output, cancellationToken);
Expand All @@ -152,5 +146,27 @@ public async Task<IDictionary<string, byte[]>> DownloadFromExternalAsync(string
}
return files;
}

public Task<IDictionary<string, byte[]>> DownloadFromInternalAsync(string payloadRootUri, CancellationToken cancellationToken = default)
{
if (!HasInternalClient())
{
throw new InvalidOperationException("Not configured for internal blob storage.");
}
BlobUriBuilder uriBuilder = new(new Uri(payloadRootUri));
string prefix = uriBuilder.BlobName;
return DownloadAsync(_internalContainerClient, prefix, cancellationToken);
}

public Task<IDictionary<string, byte[]>> DownloadFromExternalAsync(string payloadRootUri, CancellationToken cancellationToken = default)
{
if (!HasExternalClient())
{
throw new InvalidOperationException("Not configured for external blob storage.");
}
BlobUriBuilder uriBuilder = new(new Uri(payloadRootUri));
string prefix = ChangeBlobRoot(uriBuilder.BlobName);
return DownloadAsync(_externalContainerClient, prefix, cancellationToken);
}
}
}
11 changes: 8 additions & 3 deletions DotNet/Submission/Controllers/SubmissionController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ public class SubmissionController(
* Downloads the specified report's data as a ZIP archive
* <param name="facilityId">The ID of the facility</param>
* <param name="reportId">The ID of the report to download</param>
* <param name="external">Whether to download from external or internal (default) storage</param>
* <remarks>Gets information about the report from the report service in order to construct the directory/path for the report.</remarks>
*/
[HttpGet("{facilityId}/{reportId}")]
public async Task<IActionResult> DownloadReport([FromRoute] string facilityId, [FromRoute] string reportId)
public async Task<IActionResult> DownloadReport(
[FromRoute] string facilityId,
Comment thread
smailliwcs marked this conversation as resolved.
[FromRoute] string reportId,
[FromQuery] bool external = false)
{
string sanitizedFacilityId = facilityId.SanitizeAndRemove();

Expand Down Expand Up @@ -86,9 +90,10 @@ public async Task<IActionResult> DownloadReport([FromRoute] string facilityId, [
throw new Exception("Missing 'payloadRootUri' in the response.");
}

IDictionary<string, byte[]> files = await blobStorageService.DownloadFromExternalAsync(payloadRootUri.GetString());
IDictionary<string, byte[]> files = external
? await blobStorageService.DownloadFromExternalAsync(payloadRootUri.GetString())
: await blobStorageService.DownloadFromInternalAsync(payloadRootUri.GetString());

// TODO: Consider changing this to store the ZIP on disk, instead, and check if the ZIP already exists
var compressedData = this.CompressFiles(files);

return File(compressedData, "application/zip", $"{sanitizedReportId}.zip");
Expand Down
2 changes: 1 addition & 1 deletion Tests/BackendE2ETests/AdhocReportingSmokeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private async Task GenerateReport(string? measureId)
}
private async Task<Dictionary<string, Object>> DownloadReport(string reportId)
{
var request = new RestRequest($"submission/{FacilityId}/{reportId}", Method.Get);
var request = new RestRequest($"submission/{FacilityId}/{reportId}?external=true", Method.Get);
var response = await AdminBffClient.ExecuteAsync(request);
Assert.True(response.StatusCode == System.Net.HttpStatusCode.OK, $"Download Report - Expected HTTP 200 OK but received {response.StatusCode}: {response.Content}");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,7 @@ public void GETSingleMeasureAdHocSubmissionDownloadReport()
};

var client = new RestClient(options);
var request = new RestRequest($"/Submission/{TestConfig.SingleMeasureAdHocFacility}/{AdHocReportGuid}", Method.Get);
var request = new RestRequest($"/Submission/{TestConfig.SingleMeasureAdHocFacility}/{AdHocReportGuid}?external=true", Method.Get);
RestResponse response = client.ExecuteAsync(request).GetAwaiter().GetResult();
WaitForRequestComplete();
JObject jsonResponse = JObject.Parse(response.Content);
Expand Down
Loading