Skip to content

Implement IFileProviderFactory, move shared infrastructure to Umbraco.StorageProviders and support Umbraco 10 #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b3990e5
Add IFileProvider implementation
ronaldbarendse Mar 21, 2022
21211b0
Implement IFileProviderFactory and remove custom middleware
ronaldbarendse Mar 21, 2022
d34039a
Remove AzureBlobFileSystemImageProvider
ronaldbarendse Mar 21, 2022
bcead5e
Fix IAzureBlobFileSystem instance creation
ronaldbarendse Mar 21, 2022
8a42b64
Code/documentation cleanup
ronaldbarendse Mar 21, 2022
d6778b8
Move provider-independent code to Umbraco.StorageProviders project
ronaldbarendse Aug 26, 2021
7b96a0f
Update CDN config section path and documentation
ronaldbarendse Mar 22, 2022
2303f8b
Simplify build and versioning
ronaldbarendse Mar 22, 2022
8786c90
Simplify build and versioning for v2
ronaldbarendse Mar 23, 2022
7ca48b5
Fix caching of NuGet packages caching (use explicit path, add restore…
ronaldbarendse Mar 23, 2022
a1018db
Add additional constructor to allow configuration using managed ident…
ronaldbarendse Mar 23, 2022
9c141d0
Also add additional constructor on image cache
ronaldbarendse Mar 23, 2022
2d4a058
Update icon.png include
ronaldbarendse Mar 29, 2022
f5e2e40
Update to latest Umbraco v10 preview
ronaldbarendse Apr 13, 2022
87cca72
Add comment about CLSCompliantAttribute
ronaldbarendse Apr 13, 2022
77e2dc0
Remove redundant code and calls in DI extension methods
ronaldbarendse Apr 13, 2022
01bb12f
Ensure RemoveMediaFromPath also removes customized media path
ronaldbarendse Apr 13, 2022
016f849
Code cleanup (seal classes, parameter null checking, expression bodies)
ronaldbarendse Apr 13, 2022
2be5ee6
Change AnalysisMode to .NET 6 value for all
ronaldbarendse Apr 14, 2022
dc2b1e2
Install PublicApiAnalyzers and update editorconfig
ronaldbarendse Apr 14, 2022
ce61fbf
Install StyleCop.Analyzers and update code styling/documentation
ronaldbarendse Apr 14, 2022
fd349a4
Update dependency versions and fix nullability issues
ronaldbarendse May 9, 2022
22bf9a4
Re-add updated Nerdbank.GitVersioning dependency
ronaldbarendse May 9, 2022
6c1e7bf
Remove nightly MyGet feed
ronaldbarendse May 9, 2022
80f4d14
Revert GitVersioning and PublicApiAnalyzers
ronaldbarendse May 11, 2022
e2b8943
Remove version.json from solution items
ronaldbarendse May 11, 2022
8f19fff
Fix typos in README.md
ronaldbarendse May 11, 2022
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
6 changes: 4 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ indent_size = 2
dotnet_style_predefined_type_for_locals_parameters_members = true:error

dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.severity = suggestion

dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private

dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

dotnet_diagnostic.CA1054.severity = suggestion
53 changes: 53 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Prepare release

on:
workflow_dispatch:
inputs:
tag:
description: 'The prerelease tag to apply on the release branch (if any). If not specified, any existing prerelease tag will be removed.'
required: false
default: ''
type: choice
options:
- ''
- 'beta'
- 'rc'
versionIncrement:
description: 'Specifies which part of the version on the current branch is incremented.'
required: true
default: 'minor'
type: choice
options:
- 'major'
- 'minor'
- 'build'

env:
DOTNET_NOLOGO: true
DOTNET_GENERATE_ASPNET_CERTIFICATE: false
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

jobs:
prepare-release:
name: Prepare release
runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Configure git
run: |
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'

- name: Setup Nerdbank.GitVersioning
run: dotnet tool install --tool-path . nbgv

- name: Prepare release
run: ./nbgv prepare-release ${{ github.event.inputs.tag }} -p src --versionIncrement ${{ github.event.inputs.versionIncrement }}

- name: Push commit (and new branch)
run: git push --all
34 changes: 34 additions & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Publish release

on:
workflow_dispatch:

env:
DOTNET_NOLOGO: true
DOTNET_GENERATE_ASPNET_CERTIFICATE: false
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

jobs:
publish-release:
name: Publish release
runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Configure git
run: |
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'

- name: Setup Nerdbank.GitVersioning
run: dotnet tool install --tool-path . nbgv

- name: Tag release
run: ./nbgv tag -p src

- name: Push git tags
run: git push --tags
8 changes: 0 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
*.dll
*.exe
*.log
*.nupkg
*.suo
*.user

Expand All @@ -10,7 +6,3 @@
.vscode/
[Bb]in/
[Oo]bj/

Build/temp
build.out/
build.tmp/
8 changes: 0 additions & 8 deletions NuGet.config

This file was deleted.

113 changes: 60 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,84 @@
# Umbraco.StorageProviders
# Umbraco storage providers

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

## Umbraco.StorageProviders.AzureBlob

The Azure Blob Storage provider has an implementation of the Umbraco `IFileSystem` that connects to an Azure Blob Storage container.
## Umbraco.StorageProviders

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

### Usage

This provider can be added in the `Startup.cs` file:

```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddUmbraco(_env, _config)
.AddBackOffice()
.AddWebsite()
.AddComposers()
// Add the Azure Blob Storage file system, ImageSharp image provider/cache and middleware for Media:
.AddAzureBlobMediaFileSystem()
// Optionally add the CDN media URL provider:
// Add the CDN media URL provider:
.AddCdnMediaUrlProvider()
.Build();
}
```

public void Configure(IApplicationBuilder app)
There're multiple ways to configure the CDN provider, it can be done in code:

```csharp
.AddCdnMediaUrlProvider(options => {
options.Url = new Uri("https://cdn.example.com/");
});
```

In `appsettings.json`:

```json
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
"Umbraco": {
"Storage": {
"Cdn": {
"Url": "https://cdn.example.com/"
}
}

app.UseUmbraco()
.WithMiddleware(u =>
{
u.UseBackOffice();
u.UseWebsite();
// Enables the Azure Blob Storage middleware for Media:
u.UseAzureBlobMediaFileSystem();

})
.WithEndpoints(u =>
{
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
}
}
```

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

```csharp
services.AddUmbraco(_env, _config)
```sh
UMBRACO__STORAGE__CDN__URL=<CDN_BASE_URL>
```

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

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

The Azure Blob Storage provider has an implementation of the Umbraco `IFileSystem` that connects to an Azure Blob Storage container.

### Usage

This provider can be added in the `Startup.cs` file:

```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddUmbraco(_env, _config)
.AddBackOffice()
.AddWebsite()
.AddComposers()
// Add the Azure Blob Storage file system
.AddAzureBlobMediaFileSystem()
.Build();
}
```

There're multiple ways to configure the provider, it can be done in code:

```csharp
.AddAzureBlobMediaFileSystem(options => {
options.ConnectionString = "";
options.ContainerName = "";
})
```

In `appsettings.json`:
Expand All @@ -79,10 +90,7 @@ In `appsettings.json`:
"AzureBlob": {
"Media": {
"ConnectionString": "",
"ContainerName": "",
"Cdn": {
"Url": ""
}
"ContainerName": ""
}
}
}
Expand All @@ -95,22 +103,21 @@ Or by environment variables:
```sh
UMBRACO__STORAGE__AZUREBLOB__MEDIA__CONNECTIONSTRING=<CONNECTION_STRING>
UMBRACO__STORAGE__AZUREBLOB__MEDIA__CONTAINERNAME=<CONTAINER_NAME>
UMBRACO__STORAGE__AZUREBLOB__MEDIA__CDN__URL=<CDN_BASE_URL>
```

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

## Using the file system provider

Please refer to our documentation on [using custom file systems](https://our.umbraco.com/documentation/Extending/FileSystemProviders/).

## Folder structure in the Azure Blob Storage container
### Folder structure in the Azure Blob Storage container
The container name is expected to exist and uses the following folder structure:
- `/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)
- `/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)

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.

## Using the file system providers

Please refer to our documentation on [using custom file systems](https://our.umbraco.com/documentation/Extending/FileSystemProviders/).

## Bugs, issues and Pull Requests

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.
Expand Down
16 changes: 15 additions & 1 deletion Umbraco.StorageProviders.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
azure-pipelines.yml = azure-pipelines.yml
src\Directory.Build.props = src\Directory.Build.props
LICENSE = LICENSE
NuGet.config = NuGet.config
README.md = README.md
src\version.json = src\version.json
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.StorageProviders", "src\Umbraco.StorageProviders\Umbraco.StorageProviders.csproj", "{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -39,6 +41,18 @@ Global
{99A3FCBE-FDC6-4580-BDB8-7D219C6D98C3}.Release|x64.Build.0 = Release|Any CPU
{99A3FCBE-FDC6-4580-BDB8-7D219C6D98C3}.Release|x86.ActiveCfg = Release|Any CPU
{99A3FCBE-FDC6-4580-BDB8-7D219C6D98C3}.Release|x86.Build.0 = Release|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x64.ActiveCfg = Debug|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x64.Build.0 = Debug|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x86.ActiveCfg = Debug|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Debug|x86.Build.0 = Debug|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|Any CPU.Build.0 = Release|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x64.ActiveCfg = Release|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x64.Build.0 = Release|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x86.ActiveCfg = Release|Any CPU
{5EC38982-2C9A-4D8D-AAE2-743A690FCD71}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading