Skip to content

Commit f5af4a4

Browse files
Merge pull request #36 from umbraco/feature/fileproviderfactory
Implement IFileProviderFactory, move shared infrastructure to Umbraco.StorageProviders and support Umbraco 10
2 parents a33c198 + 8f19fff commit f5af4a4

34 files changed

+5550
-1489
lines changed

.editorconfig

100755100644
Lines changed: 106 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,55 @@
1-
# editorconfig.org
2-
3-
# top-most EditorConfig file
41
root = true
52

6-
# Default settings:
7-
# A newline ending every file
8-
# Use 4 spaces as indentation
93
[*]
104
insert_final_newline = true
115
end_of_line = lf
126
indent_style = space
137
indent_size = 4
14-
15-
# Trim trailing whitespace, limited support.
16-
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
178
trim_trailing_whitespace = true
189

10+
csharp_indent_braces = false
11+
csharp_indent_case_contents = true
12+
csharp_indent_labels = one_less_than_current
13+
csharp_prefer_braces = true:warning
14+
csharp_prefer_simple_default_expression = true:suggestion
15+
csharp_prefer_simple_using_statement = true:suggestion
16+
csharp_prefer_static_local_function = true:suggestion
17+
csharp_space_around_binary_operators = before_and_after
18+
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
19+
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
20+
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
21+
csharp_style_conditional_delegate_call = true:suggestion
22+
csharp_style_deconstructed_variable_declaration = true:suggestion
23+
csharp_style_expression_bodied_accessors = true:silent
24+
csharp_style_expression_bodied_constructors = true:silent
25+
csharp_style_expression_bodied_indexers = true:silent
26+
csharp_style_expression_bodied_lambdas = true:silent
27+
csharp_style_expression_bodied_local_functions = false:silent
28+
csharp_style_expression_bodied_methods = true:silent
29+
csharp_style_expression_bodied_operators = true:silent
30+
csharp_style_expression_bodied_properties = true:silent
31+
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
32+
csharp_style_inlined_variable_declaration = true:suggestion
33+
csharp_style_namespace_declarations = block_scoped:silent
34+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
35+
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
36+
csharp_style_prefer_extended_property_pattern = true:suggestion
37+
csharp_style_prefer_index_operator = true:suggestion
38+
csharp_style_prefer_local_over_anonymous_function = true:suggestion
39+
csharp_style_prefer_not_pattern = true:suggestion
40+
csharp_style_prefer_null_check_over_type_check = true:suggestion
41+
csharp_style_prefer_pattern_matching = true:silent
42+
csharp_style_prefer_range_operator = true:suggestion
43+
csharp_style_prefer_switch_expression = true:suggestion
44+
csharp_style_prefer_tuple_swap = true:suggestion
45+
csharp_style_throw_expression = true:suggestion
46+
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
47+
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
48+
csharp_style_var_elsewhere = false:silent
49+
csharp_style_var_for_built_in_types = false:silent
50+
csharp_style_var_when_type_is_apparent = false:silent
51+
csharp_using_directive_placement = outside_namespace:silent
52+
1953
[*.md]
2054
insert_final_newline = false
2155
trim_trailing_whitespace = false
@@ -24,14 +58,70 @@ trim_trailing_whitespace = false
2458
indent_size = 2
2559

2660
[*.{cs,vb}]
27-
dotnet_style_predefined_type_for_locals_parameters_members = true:error
61+
tab_width = 4
2862

29-
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
30-
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
63+
dotnet_code_quality_unused_parameters = all:suggestion
3164
dotnet_naming_rule.private_members_with_underscore.severity = suggestion
32-
33-
dotnet_naming_symbols.private_fields.applicable_kinds = field
34-
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
35-
65+
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
66+
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
3667
dotnet_naming_style.prefix_underscore.capitalization = camel_case
3768
dotnet_naming_style.prefix_underscore.required_prefix = _
69+
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
70+
dotnet_naming_symbols.private_fields.applicable_kinds = field
71+
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
72+
dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
73+
dotnet_style_coalesce_expression = true:suggestion
74+
dotnet_style_collection_initializer = true:suggestion
75+
dotnet_style_explicit_tuple_names = true:suggestion
76+
dotnet_style_namespace_match_folder = true:suggestion
77+
dotnet_style_null_propagation = true:suggestion
78+
dotnet_style_object_initializer = true:suggestion
79+
dotnet_style_operator_placement_when_wrapping = beginning_of_line
80+
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
81+
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
82+
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
83+
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
84+
dotnet_style_predefined_type_for_locals_parameters_members = true:error
85+
dotnet_style_predefined_type_for_member_access = true:silent
86+
dotnet_style_prefer_auto_properties = true:silent
87+
dotnet_style_prefer_compound_assignment = true:suggestion
88+
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
89+
dotnet_style_prefer_conditional_expression_over_return = true:silent
90+
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
91+
dotnet_style_prefer_inferred_tuple_names = true:suggestion
92+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
93+
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
94+
dotnet_style_prefer_simplified_interpolation = true:suggestion
95+
dotnet_style_qualification_for_event = false:silent
96+
dotnet_style_qualification_for_field = false:silent
97+
dotnet_style_qualification_for_method = false:silent
98+
dotnet_style_qualification_for_property = false:silent
99+
dotnet_style_readonly_field = true:suggestion
100+
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
101+
102+
# CA1054: URI parameters should not be strings
103+
dotnet_diagnostic.CA1054.severity = suggestion
104+
105+
# CA1055: URI-like return values should not be strings
106+
dotnet_diagnostic.CA1055.severity = none
107+
108+
# RS0048: Missing shipped or unshipped public API file
109+
dotnet_public_api_analyzer.require_api_files = true
110+
111+
# SA1101: Prefix local calls with this
112+
dotnet_diagnostic.SA1101.severity = none
113+
114+
# SA1309: Field names should not begin with underscore
115+
dotnet_diagnostic.SA1309.severity = none
116+
117+
# SA1413: Use trailing comma in multi-line initializers
118+
dotnet_diagnostic.SA1413.severity = none
119+
120+
# SA1502: Element should not be on a single line
121+
dotnet_diagnostic.SA1502.severity = none
122+
123+
# SA1625: Element documentation should not be copied and pasted
124+
dotnet_diagnostic.SA1625.severity = none
125+
126+
# SA1633: File should have header
127+
dotnet_diagnostic.SA1633.severity = none

.gitignore

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
*.dll
2-
*.exe
3-
*.log
4-
*.nupkg
51
*.suo
62
*.user
73

@@ -10,7 +6,3 @@
106
.vscode/
117
[Bb]in/
128
[Oo]bj/
13-
14-
Build/temp
15-
build.out/
16-
build.tmp/

NuGet.config

Lines changed: 0 additions & 8 deletions
This file was deleted.

README.md

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,84 @@
1-
# Umbraco.StorageProviders
1+
# Umbraco storage providers
22

33
This repository contains Umbraco storage providers that can replace the default physical file storage.
44

5-
## Umbraco.StorageProviders.AzureBlob
6-
7-
The Azure Blob Storage provider has an implementation of the Umbraco `IFileSystem` that connects to an Azure Blob Storage container.
5+
## Umbraco.StorageProviders
86

9-
It also has the following features:
10-
- middleware for serving media files from the `/media` path
11-
- ImageSharp image provider/cache
12-
- a CDN media URL provider
7+
Contains shared storage providers infrastructure, like a CDN media URL provider.
138

149
### Usage
1510

16-
This provider can be added in the `Startup.cs` file:
17-
1811
```csharp
1912
public void ConfigureServices(IServiceCollection services)
2013
{
2114
services.AddUmbraco(_env, _config)
2215
.AddBackOffice()
2316
.AddWebsite()
2417
.AddComposers()
25-
// Add the Azure Blob Storage file system, ImageSharp image provider/cache and middleware for Media:
26-
.AddAzureBlobMediaFileSystem()
27-
// Optionally add the CDN media URL provider:
18+
// Add the CDN media URL provider:
2819
.AddCdnMediaUrlProvider()
2920
.Build();
3021
}
22+
```
23+
24+
There are multiple ways to configure the CDN provider. It can be done in code:
25+
26+
```csharp
27+
.AddCdnMediaUrlProvider(options => {
28+
options.Url = new Uri("https://cdn.example.com/");
29+
});
30+
```
31+
32+
In `appsettings.json`:
3133

32-
public void Configure(IApplicationBuilder app)
34+
```json
3335
{
34-
if (env.IsDevelopment())
35-
{
36-
app.UseDeveloperExceptionPage();
36+
"Umbraco": {
37+
"Storage": {
38+
"Cdn": {
39+
"Url": "https://cdn.example.com/"
40+
}
3741
}
38-
39-
app.UseUmbraco()
40-
.WithMiddleware(u =>
41-
{
42-
u.UseBackOffice();
43-
u.UseWebsite();
44-
// Enables the Azure Blob Storage middleware for Media:
45-
u.UseAzureBlobMediaFileSystem();
46-
47-
})
48-
.WithEndpoints(u =>
49-
{
50-
u.UseInstallerEndpoints();
51-
u.UseBackOfficeEndpoints();
52-
u.UseWebsiteEndpoints();
53-
});
42+
}
5443
}
5544
```
5645

57-
There're multiple ways to configure the provider, it can be done in code:
46+
Or by environment variables:
5847

59-
```csharp
60-
services.AddUmbraco(_env, _config)
48+
```sh
49+
UMBRACO__STORAGE__CDN__URL=<CDN_BASE_URL>
50+
```
6151

62-
.AddAzureBlobMediaFileSystem(options => {
63-
options.ConnectionString = "";
64-
options.ContainerName = "";
65-
})
52+
_Note: you still have to add the provider in the `Startup.cs` file when not configuring the options in code._
6653

67-
.AddCdnMediaUrlProvider(options => {
68-
options.Url = new Uri("https://my-cdn.example.com/");
69-
});
54+
## Umbraco.StorageProviders.AzureBlob
7055

56+
The Azure Blob Storage provider has an implementation of the Umbraco `IFileSystem` that connects to an Azure Blob Storage container.
57+
58+
### Usage
59+
60+
This provider can be added in the `Startup.cs` file:
61+
62+
```csharp
63+
public void ConfigureServices(IServiceCollection services)
64+
{
65+
services.AddUmbraco(_env, _config)
66+
.AddBackOffice()
67+
.AddWebsite()
68+
.AddComposers()
69+
// Add the Azure Blob Storage file system
70+
.AddAzureBlobMediaFileSystem()
71+
.Build();
72+
}
73+
```
74+
75+
There are multiple ways to configure the provider. It can be done in code:
76+
77+
```csharp
78+
.AddAzureBlobMediaFileSystem(options => {
79+
options.ConnectionString = "";
80+
options.ContainerName = "";
81+
})
7182
```
7283

7384
In `appsettings.json`:
@@ -79,10 +90,7 @@ In `appsettings.json`:
7990
"AzureBlob": {
8091
"Media": {
8192
"ConnectionString": "",
82-
"ContainerName": "",
83-
"Cdn": {
84-
"Url": ""
85-
}
93+
"ContainerName": ""
8694
}
8795
}
8896
}
@@ -95,22 +103,21 @@ Or by environment variables:
95103
```sh
96104
UMBRACO__STORAGE__AZUREBLOB__MEDIA__CONNECTIONSTRING=<CONNECTION_STRING>
97105
UMBRACO__STORAGE__AZUREBLOB__MEDIA__CONTAINERNAME=<CONTAINER_NAME>
98-
UMBRACO__STORAGE__AZUREBLOB__MEDIA__CDN__URL=<CDN_BASE_URL>
99106
```
100107

101108
_Note: you still have to add the provider in the `Startup.cs` file when not configuring the options in code._
102109

103-
## Using the file system provider
104-
105-
Please refer to our documentation on [using custom file systems](https://our.umbraco.com/documentation/Extending/FileSystemProviders/).
106-
107-
## Folder structure in the Azure Blob Storage container
110+
### Folder structure in the Azure Blob Storage container
108111
The container name is expected to exist and uses the following folder structure:
109112
- `/media` - contains the Umbraco media, stored in the structure defined by the `IMediaPathScheme` registered in Umbraco (the default `UniqueMediaPathScheme` stores files with their original filename in 8 character directories, based on the content and property GUID identifier)
110113
- `/cache` - contains the ImageSharp image cache, stored as files with a filename defined by the `ICacheHash` registered in ImageSharp (the default `CacheHash` generates SHA256 hashes of the file contents and uses the first characters configured by the `Umbraco:CMS:Imaging:CachedNameLength` setting)
111114

112115
Note that this is different than the behavior of other file system providers - i.e. https://github.com/umbraco-community/UmbracoFileSystemProviders.Azure that expect the media contents to be at the root level.
113116

117+
## Using the file system providers
118+
119+
Please refer to our documentation on [using custom file systems](https://our.umbraco.com/documentation/Extending/FileSystemProviders/).
120+
114121
## Bugs, issues and Pull Requests
115122

116123
If you encounter a bug when using this client library you are welcome to open an issue in the issue tracker of this repository. We always welcome Pull Request and please feel free to open an issue before submitting a Pull Request to discuss what you want to submit.

Umbraco.StorageProviders.sln

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1313
azure-pipelines.yml = azure-pipelines.yml
1414
src\Directory.Build.props = src\Directory.Build.props
1515
LICENSE = LICENSE
16-
NuGet.config = NuGet.config
1716
README.md = README.md
1817
EndProjectSection
1918
EndProject
19+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.StorageProviders", "src\Umbraco.StorageProviders\Umbraco.StorageProviders.csproj", "{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}"
20+
EndProject
2021
Global
2122
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2223
Debug|Any CPU = Debug|Any CPU
@@ -39,6 +40,18 @@ Global
3940
{99A3FCBE-FDC6-4580-BDB8-7D219C6D98C3}.Release|x64.Build.0 = Release|Any CPU
4041
{99A3FCBE-FDC6-4580-BDB8-7D219C6D98C3}.Release|x86.ActiveCfg = Release|Any CPU
4142
{99A3FCBE-FDC6-4580-BDB8-7D219C6D98C3}.Release|x86.Build.0 = Release|Any CPU
43+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|Any CPU.Build.0 = Debug|Any CPU
45+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x64.ActiveCfg = Debug|Any CPU
46+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x64.Build.0 = Debug|Any CPU
47+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x86.ActiveCfg = Debug|Any CPU
48+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x86.Build.0 = Debug|Any CPU
49+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|Any CPU.ActiveCfg = Release|Any CPU
50+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|Any CPU.Build.0 = Release|Any CPU
51+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x64.ActiveCfg = Release|Any CPU
52+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x64.Build.0 = Release|Any CPU
53+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x86.ActiveCfg = Release|Any CPU
54+
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x86.Build.0 = Release|Any CPU
4255
EndGlobalSection
4356
GlobalSection(SolutionProperties) = preSolution
4457
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)