33using System . IO ;
44using System . Linq ;
55using System . Threading . Tasks ;
6+ using System . Web ;
67using System . Web . Hosting ;
78using SmartStore . Utilities ;
89
910namespace SmartStore . Core . IO
1011{
1112 public class LocalFileSystem : IFileSystem
1213 {
13- private readonly string _basePath ; // /base
14- private readonly string _virtualPath ; // ~/base
15- private readonly string _publicPath ; // /Shop/base
16- private readonly string _storagePath ; // C:\SMNET\base
14+ private string _root ;
15+ private string _publicPath ; // /Shop/base
16+ private string _storagePath ; // C:\SMNET\base
1717
1818 public LocalFileSystem ( )
19- : this ( string . Empty )
19+ : this ( string . Empty , string . Empty )
2020 {
2121 }
2222
2323 protected internal LocalFileSystem ( string basePath )
24+ : this ( basePath , string . Empty )
2425 {
25- // for testing purposes
26- _basePath = basePath . EmptyNull ( ) . EnsureStartsWith ( "/" ) . TrimEnd ( '/' ) ;
26+ }
27+
28+ protected internal LocalFileSystem ( string basePath , string publicPath )
29+ {
30+ basePath = basePath . EmptyNull ( ) ;
31+
32+ var pathIsAbsolute = FileSystemHelper . IsFullPath ( basePath ) ;
2733
28- _virtualPath = "~" + _basePath ;
34+ NormalizeStoragePath ( ref basePath , pathIsAbsolute ) ;
2935
30- _storagePath = CommonHelper . MapPath ( _virtualPath , false ) ;
36+ _publicPath = NormalizePublicPath ( publicPath , basePath , pathIsAbsolute ) ;
3137
32- var appPath = "" ;
38+ _root = basePath ;
39+ }
40+
41+ private void NormalizeStoragePath ( ref string basePath , bool basePathIsAbsolute )
42+ {
43+ if ( basePathIsAbsolute )
44+ {
45+ // Path is fully qualified (UNC or absolute with drive letter)
46+
47+ // In this case this is our root path...
48+ basePath = basePath . TrimEnd ( Path . DirectorySeparatorChar ) ;
49+
50+ // ...AND our physical storage path
51+ _storagePath = basePath ;
52+ }
53+ else
54+ {
55+ // Path is relative to the app root
56+ basePath = basePath . TrimEnd ( '/' ) . EnsureStartsWith ( "/" ) ;
57+ _storagePath = CommonHelper . MapPath ( "~" + basePath , false ) ;
58+ }
59+ }
60+
61+ private string NormalizePublicPath ( string publicPath , string basePath , bool basePathIsAbsolute )
62+ {
63+ publicPath = publicPath . EmptyNull ( ) ;
64+
65+ if ( basePathIsAbsolute )
66+ {
67+ if ( publicPath . IsEmpty ( ) || ( ! publicPath . StartsWith ( "~/" ) && ! publicPath . IsWebUrl ( true ) ) )
68+ {
69+ throw new ArgumentException ( "When the base path is a fully qualified path, the public path must not be empty, and either be a fully qualified URL or a virtual path (e.g.: ~/Media)" , nameof ( publicPath ) ) ;
70+ }
71+ }
72+
73+ var appVirtualPath = HostingEnvironment . IsHosted
74+ ? HostingEnvironment . ApplicationVirtualPath . TrimEnd ( '/' )
75+ : string . Empty ;
76+
77+ if ( publicPath . StartsWith ( "~/" ) )
78+ {
79+ // prepend application virtual path
80+ return appVirtualPath + publicPath . Substring ( 1 ) ;
81+ }
3382
34- if ( HostingEnvironment . IsHosted )
83+ if ( publicPath . IsEmpty ( ) )
3584 {
36- appPath = HostingEnvironment . ApplicationVirtualPath ;
85+ // > /MyAppRoot/Media
86+ return appVirtualPath + basePath ;
3787 }
3888
39- _publicPath = appPath . TrimEnd ( '/' ) + _basePath ;
89+ return publicPath ;
4090 }
4191
4292 public string Root
4393 {
44- get { return _basePath ; }
94+ get { return _root ; }
4595 }
4696
4797 /// <summary>
@@ -62,7 +112,7 @@ protected virtual string MapStorage(string path)
62112 /// <returns>The relative path combined with the public path in an URL friendly format ('/' character for directory separator).</returns>
63113 protected virtual string MapPublic ( string path )
64114 {
65- return string . IsNullOrEmpty ( path ) ? _publicPath : Path . Combine ( _publicPath , path ) . Replace ( Path . DirectorySeparatorChar , '/' ) . Replace ( " " , "%20" ) ;
115+ return string . IsNullOrEmpty ( path ) ? _publicPath : HttpUtility . UrlDecode ( Path . Combine ( _publicPath , path ) . Replace ( Path . DirectorySeparatorChar , '/' ) ) ;
66116 }
67117
68118 static string Fix ( string path )
@@ -83,14 +133,14 @@ public virtual string GetStoragePath(string url)
83133 {
84134 if ( url . HasValue ( ) )
85135 {
86- if ( url . StartsWith ( _virtualPath ) )
136+ if ( url . StartsWith ( "~/" ) )
87137 {
88- return url . Substring ( _virtualPath . Length ) . Replace ( '/' , Path . DirectorySeparatorChar ) . Replace ( "%20" , " " ) ;
138+ url = VirtualPathUtility . ToAbsolute ( url ) ;
89139 }
90140
91141 if ( url . StartsWith ( _publicPath ) )
92142 {
93- return url . Substring ( _publicPath . Length ) . Replace ( '/' , Path . DirectorySeparatorChar ) . Replace ( "%20" , " " ) ;
143+ return HttpUtility . UrlDecode ( url . Substring ( _publicPath . Length ) . Replace ( '/' , Path . DirectorySeparatorChar ) ) ;
94144 }
95145 }
96146
0 commit comments