Skip to content

Commit f48e9df

Browse files
authored
Paje/try to fix a bug where upload many files bricks the browser (#25)
* fix the global json so we can use an 6.x.x release of dotnet * limit the parallel task for uploading * fix the file upload dialog * update packages * remove local settings from publish * fixes all code style issues and make the project aware of nullable * apply some small fixes to the local development files * remove css * fix the parallel upload finally * update packages
1 parent eea403e commit f48e9df

File tree

14 files changed

+164
-141
lines changed

14 files changed

+164
-141
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,4 +456,6 @@ $RECYCLE.BIN/
456456
##
457457
## CZ.Azure.FileExchange
458458
temp/*
459-
**/wwwroot/client/
459+
**/wwwroot/client/
460+
### remove all css files from git, because we use scss
461+
*.css

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
33
"version": "6.0.200",
4-
"rollForward": "latestPatch"
4+
"rollForward": "latestMajor"
55
}
66
}

src/CZ.Azure.FileExchange.Api/CZ.Azure.FileExchange.Api.csproj

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFramework>net6.0</TargetFramework>
44
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
5+
<Nullable>enable</Nullable>
56
</PropertyGroup>
67
<ItemGroup>
7-
<PackageReference Include="Azure.Storage.Blobs" Version="12.10.0" />
8-
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.1.0" />
9-
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" />
8+
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
9+
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.4.0" />
10+
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
1011
</ItemGroup>
1112
<ItemGroup>
1213
<None Update="host.json">
1314
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1415
</None>
1516
<None Update="local.settings.json">
16-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
17+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
1718
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
1819
</None>
1920
</ItemGroup>

src/CZ.Azure.FileExchange.Api/GenerateSas.cs

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
namespace CZ.Azure.FileExchange.Api;
2+
13
using System;
24
using System.Net;
35
using System.Threading.Tasks;
@@ -8,96 +10,90 @@
810
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
911
using Microsoft.Extensions.Logging;
1012
using Microsoft.OpenApi.Models;
11-
using Azure.Storage.Blobs;
12-
using Azure.Storage.Sas;
13+
using global::Azure.Storage.Blobs;
14+
using global::Azure.Storage.Sas;
1315
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
1416
using System.Net.Http;
1517

16-
namespace CZ.Azure.FileExchange.Api
18+
public class GenerateSas
1719
{
18-
public class GenerateSas
20+
private readonly ILogger<GenerateSas> logger;
21+
22+
public GenerateSas(ILogger<GenerateSas> log) =>
23+
this.logger = log;
24+
25+
[FunctionName("GenerateSas")]
26+
[OpenApiOperation(operationId: "Run")]
27+
[OpenApiParameter(name: "filecode", In = ParameterLocation.Query, Required = false, Type = typeof(string), Description = "The **code** parameter, that represent to get read access to stored files")]
28+
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Description = "The OK response")]
29+
public async Task<IActionResult> Run(
30+
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req)
1931
{
20-
private readonly ILogger<GenerateSas> _logger;
32+
this.logger.LogInformation("Start generating SaS");
2133

22-
public GenerateSas(ILogger<GenerateSas> log)
34+
var blobservice = new BlobServiceClient(GetEnvironmentVariable("StorageConnectionString"));
35+
Uri? uri;
36+
BlobContainerClient? blobContainerClient;
37+
if (req.Query.TryGetValue("filecode", out var code))
38+
{
39+
blobContainerClient = blobservice.GetBlobContainerClient(code);
40+
uri = this.GetServiceSasUriForContainer(blobContainerClient, BlobSasPermissions.Read | BlobSasPermissions.List);
41+
}
42+
else
43+
{
44+
var response = await blobservice.CreateBlobContainerAsync(Guid.NewGuid().ToString());
45+
_ = response.ThrowIfNullOrDefault();
46+
blobContainerClient = response.Value;
47+
uri = this.GetServiceSasUriForContainer(blobContainerClient);
48+
}
49+
if (uri == null)
2350
{
24-
_logger = log;
51+
this.logger.LogError("Failed to generate the Sas token");
52+
return new BadRequestObjectResult(new StringContent("Failed to greate SaS token to upload your files. Please try again."));
2553
}
2654

27-
[FunctionName("GenerateSas")]
28-
[OpenApiOperation(operationId: "Run")]
29-
[OpenApiParameter(name: "filecode", In = ParameterLocation.Query, Required = false, Type = typeof(string), Description = "The **code** parameter, that represent to get read access to stored files")]
30-
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "text/plain", bodyType: typeof(string), Description = "The OK response")]
31-
public async Task<IActionResult> Run(
32-
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req)
55+
return new OkObjectResult(uri.ToString());
56+
}
57+
58+
private static string GetEnvironmentVariable(string name) =>
59+
Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process) ??
60+
throw new ArgumentException($"The setting for {name} is missing.");
61+
private Uri? GetServiceSasUriForContainer(
62+
BlobContainerClient containerClient,
63+
BlobSasPermissions permission = BlobSasPermissions.Write | BlobSasPermissions.Read | BlobSasPermissions.List,
64+
string? storedPolicyName = null
65+
)
66+
{
67+
// Check whether this BlobContainerClient object has been authorized with Shared Key.
68+
if (containerClient.CanGenerateSasUri)
3369
{
34-
_logger.LogInformation("Start generating SaS");
70+
// Create a SAS token that's valid for one hour.
71+
var sasBuilder = new BlobSasBuilder()
72+
{
73+
BlobContainerName = containerClient.Name,
74+
Resource = "c"
75+
};
3576

36-
var blobservice = new BlobServiceClient(GetEnvironmentVariable("StorageConnectionString"));
37-
BlobContainerClient? blobContainerClient = null;
38-
Uri uri = null;
39-
if(req.Query.TryGetValue("filecode", out var code))
77+
if (storedPolicyName == null)
4078
{
41-
blobContainerClient = blobservice.GetBlobContainerClient(code);
42-
uri = GetServiceSasUriForContainer(blobContainerClient, BlobSasPermissions.Read | BlobSasPermissions.List);
79+
sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
80+
sasBuilder.SetPermissions(permission);
4381
}
4482
else
4583
{
46-
var response = await blobservice.CreateBlobContainerAsync(Guid.NewGuid().ToString());
47-
response.ThrowIfNullOrDefault();
48-
blobContainerClient = response.Value;
49-
uri = GetServiceSasUriForContainer(blobContainerClient);
50-
}
51-
if (uri == null)
52-
{
53-
_logger.LogError("Failed to generate the Sas token");
54-
new BadRequestObjectResult(new StringContent("Failed to greate SaS token to upload your files. Please try again."));
84+
sasBuilder.Identifier = storedPolicyName;
5585
}
5686

57-
return new OkObjectResult(uri.ToString());
58-
}
87+
var sasUri = containerClient.GenerateSasUri(sasBuilder);
88+
this.logger.LogInformation("SAS URI for blob container is: {0}", sasUri);
5989

60-
private static string GetEnvironmentVariable(string name)
61-
{
62-
return System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
90+
return sasUri;
6391
}
64-
private Uri GetServiceSasUriForContainer(
65-
BlobContainerClient containerClient,
66-
BlobSasPermissions permission = BlobSasPermissions.Write | BlobSasPermissions.Read | BlobSasPermissions.List,
67-
string storedPolicyName = null
68-
)
92+
else
6993
{
70-
// Check whether this BlobContainerClient object has been authorized with Shared Key.
71-
if (containerClient.CanGenerateSasUri)
72-
{
73-
// Create a SAS token that's valid for one hour.
74-
BlobSasBuilder sasBuilder = new BlobSasBuilder()
75-
{
76-
BlobContainerName = containerClient.Name,
77-
Resource = "c"
78-
};
79-
80-
if (storedPolicyName == null)
81-
{
82-
sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
83-
sasBuilder.SetPermissions(permission);
84-
}
85-
else
86-
{
87-
sasBuilder.Identifier = storedPolicyName;
88-
}
89-
90-
Uri sasUri = containerClient.GenerateSasUri(sasBuilder);
91-
_logger.LogInformation("SAS URI for blob container is: {0}", sasUri);
92-
93-
return sasUri;
94-
}
95-
else
96-
{
97-
_logger.LogError(@"BlobContainerClient must be authorized with Shared Key
94+
this.logger.LogError(@"BlobContainerClient must be authorized with Shared Key
9895
credentials to create a service SAS.");
99-
return null;
100-
}
96+
return null;
10197
}
10298
}
10399
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"profiles": {
33
}
4-
}
4+
}

src/CZ.Azure.FileExchange.Api/Properties/serviceDependencies.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
"appInsights1": {
44
"type": "appInsights"
55
},
6-
"storage1": {
6+
"StorageConnectionString": {
77
"type": "storage",
88
"connectionId": "AzureWebJobsStorage"
99
}
1010
}
11-
}
11+
}

src/CZ.Azure.FileExchange.Api/Properties/serviceDependencies.local.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
"appInsights1": {
44
"type": "appInsights.sdk"
55
},
6-
"storage1": {
6+
"StorageConnectionString": {
77
"type": "storage.emulator",
88
"connectionId": "AzureWebJobsStorage"
99
}
1010
}
11-
}
11+
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"version": "2.0",
3-
"logging": {
4-
"applicationInsights": {
5-
"samplingSettings": {
6-
"isEnabled": true,
7-
"excludedTypes": "Request"
8-
}
9-
}
3+
"logging": {
4+
"applicationInsights": {
5+
"samplingSettings": {
6+
"isEnabled": true,
7+
"excludedTypes": "Request"
8+
}
109
}
11-
}
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"IsEncrypted": false,
3+
"Values": {
4+
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
5+
"StorageConnectionString": "DefaultEndpointsProtocol=http;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
6+
},
7+
"Host": {
8+
"CORS": "*",
9+
"CORSCredentials": false
10+
}
11+
}

src/CZ.Azure.FileExchange/CZ.Azure.FileExchange.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
<ItemGroup>
1010
<PackageReference Include="DartSassBuilder" Version="0.2.1-beta" />
11-
<PackageReference Include="Azure.Storage.Blobs" Version="12.10.0" />
12-
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.2" />
13-
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.2" PrivateAssets="all" />
11+
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
12+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.11" />
13+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.11" PrivateAssets="all" />
1414
</ItemGroup>
1515

1616
<!-- SASS options -->

0 commit comments

Comments
 (0)