22// Licensed under the Apache License, Version 2.0.
33
44using System ;
5+ using System . IO ;
56using System . Threading . Tasks ;
67using Microsoft . AspNetCore . Hosting ;
78using Microsoft . AspNetCore . Http ;
89using Microsoft . AspNetCore . Http . Extensions ;
910using Microsoft . Extensions . FileProviders ;
11+ using Microsoft . Extensions . Options ;
1012using SixLabors . ImageSharp . Web . Resolvers ;
1113
1214namespace SixLabors . ImageSharp . Web . Providers
@@ -29,9 +31,11 @@ public class PhysicalFileSystemProvider : IImageProvider
2931 /// <summary>
3032 /// Initializes a new instance of the <see cref="PhysicalFileSystemProvider"/> class.
3133 /// </summary>
34+ /// <param name="options">The provider configuration options.</param>
3235 /// <param name="environment">The environment used by this middleware.</param>
3336 /// <param name="formatUtilities">Contains various format helper methods based on the current configuration.</param>
3437 public PhysicalFileSystemProvider (
38+ IOptions < PhysicalFileSystemProviderOptions > options ,
3539#if NETCOREAPP2_1
3640 IHostingEnvironment environment ,
3741#else
@@ -40,9 +44,18 @@ public PhysicalFileSystemProvider(
4044 FormatUtilities formatUtilities )
4145 {
4246 Guard . NotNull ( environment , nameof ( environment ) ) ;
43- Guard . NotNull ( environment . WebRootFileProvider , nameof ( environment . WebRootFileProvider ) ) ;
4447
45- this . fileProvider = environment . WebRootFileProvider ;
48+ // ContentRootPath is never null.
49+ // https://github.com/dotnet/aspnetcore/blob/b89eba6c3cda331ee98063e3c4a04267ec540315/src/Hosting/Hosting/src/WebHostBuilder.cs#L262
50+ Guard . NotNullOrWhiteSpace ( environment . WebRootPath , nameof ( environment . WebRootPath ) ) ;
51+
52+ // Allow configuration of the provider without having to register everything
53+ PhysicalFileSystemProviderOptions providerOptions = options != null ? options . Value : new ( ) ;
54+ string providerRootPath = GetProviderRoot ( providerOptions , environment . WebRootPath , environment . ContentRootPath ) ;
55+
56+ // Ensure provider directory is created before initializing the file provider
57+ Directory . CreateDirectory ( providerRootPath ) ;
58+ this . fileProvider = new PhysicalFileProvider ( providerRootPath ) ;
4659 this . formatUtilities = formatUtilities ;
4760 }
4861
@@ -71,5 +84,23 @@ public Task<IImageResolver> GetAsync(HttpContext context)
7184 var metadata = new ImageMetadata ( fileInfo . LastModified . UtcDateTime , fileInfo . Length ) ;
7285 return Task . FromResult < IImageResolver > ( new PhysicalFileSystemResolver ( fileInfo , metadata ) ) ;
7386 }
87+
88+ /// <summary>
89+ /// Determine the provider root path
90+ /// </summary>
91+ /// <param name="providerOptions">The provider options.</param>
92+ /// <param name="webRootPath">The web root path.</param>
93+ /// <param name="contentRootPath">The content root path.</param>
94+ /// <returns><see cref="string"/> representing the fully qualified provider root path.</returns>
95+ internal static string GetProviderRoot ( PhysicalFileSystemProviderOptions providerOptions , string webRootPath , string contentRootPath )
96+ {
97+ string providerRoot = string . IsNullOrWhiteSpace ( providerOptions . ProviderRootPath )
98+ ? webRootPath
99+ : providerOptions . ProviderRootPath ;
100+
101+ return Path . IsPathFullyQualified ( providerRoot )
102+ ? providerRoot
103+ : Path . GetFullPath ( providerRoot , contentRootPath ) ;
104+ }
74105 }
75106}
0 commit comments