@@ -110,6 +110,14 @@ public virtual Stream OpenWrite(string blobUrl)
110110
111111 public virtual async Task < Stream > OpenWriteAsync ( string blobUrl )
112112 {
113+ if ( string . IsNullOrEmpty ( blobUrl ) )
114+ {
115+ throw new ArgumentNullException ( nameof ( blobUrl ) ) ;
116+ }
117+
118+ // Normilize Url if blobUrl has wrong encoded, like contains space
119+ blobUrl = NormalizeUrl ( blobUrl ) ;
120+
113121 var filePath = GetFilePathFromUrl ( blobUrl ) ;
114122 var fileName = Path . GetFileName ( filePath ) ;
115123
@@ -147,12 +155,24 @@ public virtual async Task<Stream> OpenWriteAsync(string blobUrl)
147155 return new FlushLessStream ( await blob . OpenWriteAsync ( true , options ) ) ;
148156 }
149157
158+ protected static string NormalizeUrl ( string blobUrl )
159+ {
160+ try
161+ {
162+ return ( new Uri ( blobUrl ) ) . AbsoluteUri ;
163+ }
164+ catch ( Exception )
165+ {
166+ return blobUrl ;
167+ }
168+ }
169+
150170 public virtual async Task RemoveAsync ( string [ ] urls )
151171 {
152172 foreach ( var url in urls . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) )
153173 {
154174 var absoluteUri = url . IsAbsoluteUrl ( )
155- ? new Uri ( url ) . ToString ( )
175+ ? url
156176 : UrlHelperExtensions . Combine ( _blobServiceClient . Uri . ToString ( ) , url ) ;
157177 var blobContainer = GetBlobContainer ( GetContainerNameFromUrl ( absoluteUri ) ) ;
158178
@@ -215,11 +235,15 @@ public virtual async Task<BlobEntrySearchResult> SearchAsync(string folderUrl, s
215235 . Split ( new [ ] { Delimiter } , StringSplitOptions . RemoveEmptyEntries )
216236 . Last ( ) ;
217237
218- folder . Url = UrlHelperExtensions . Combine ( baseUriEscaped , EscapeUri ( blobhierarchyItem . Prefix ) ) ;
238+ var folderUrlBuilder = new UriBuilder ( new Uri ( baseUriEscaped ) ) ;
239+ folderUrlBuilder . Path += Delimiter + blobhierarchyItem . Prefix ;
240+ folder . Url = folderUrlBuilder . ToString ( ) ;
219241 folder . ParentUrl = GetParentUrl ( baseUriEscaped , blobhierarchyItem . Prefix ) ;
220242 folder . RelativeUrl = folder . Url . Replace ( EscapeUri ( _blobServiceClient . Uri . ToString ( ) ) , string . Empty ) ;
243+
221244 folder . CreatedDate = containerProperties . Value . LastModified . UtcDateTime ;
222245 folder . ModifiedDate = containerProperties . Value . LastModified . UtcDateTime ;
246+
223247 result . Results . Add ( folder ) ;
224248 }
225249 else
@@ -246,7 +270,11 @@ public virtual async Task<BlobEntrySearchResult> SearchAsync(string folderUrl, s
246270 {
247271 var folder = AbstractTypeFactory < BlobFolder > . TryCreateInstance ( ) ;
248272 folder . Name = item . Name . Split ( Delimiter ) . Last ( ) ;
249- folder . Url = EscapeUri ( UrlHelperExtensions . Combine ( _blobServiceClient . Uri . ToString ( ) , item . Name ) ) ;
273+
274+ var folderUrlBuilder = new UriBuilder ( _blobServiceClient . Uri ) ;
275+ folderUrlBuilder . Path += item . Name + Delimiter ;
276+ folder . Url = folderUrlBuilder . ToString ( ) ;
277+
250278 result . Results . Add ( folder ) ;
251279 }
252280 }
@@ -258,15 +286,20 @@ public virtual async Task<BlobEntrySearchResult> SearchAsync(string folderUrl, s
258286
259287 public virtual async Task CreateFolderAsync ( BlobFolder folder )
260288 {
261- var path = folder . ParentUrl == null ?
262- folder . Name :
263- UrlHelperExtensions . Combine ( folder . ParentUrl , folder . Name ) ;
289+ var newFolderUrl = folder . Name ;
264290
265- var containerName = GetContainerNameFromUrl ( path ) ;
291+ if ( folder . ParentUrl != null )
292+ {
293+ var newFolderUriBuilder = new UriBuilder ( new Uri ( folder . ParentUrl ) ) ;
294+ newFolderUriBuilder . Path += Delimiter + folder . Name ;
295+ newFolderUrl = newFolderUriBuilder . ToString ( ) ;
296+ }
297+
298+ var containerName = GetContainerNameFromUrl ( newFolderUrl ) ;
266299 var container = _blobServiceClient . GetBlobContainerClient ( containerName ) ;
267300 await container . CreateIfNotExistsAsync ( PublicAccessType . Blob ) ;
268301
269- var directoryPath = GetDirectoryPathFromUrl ( path ) ;
302+ var directoryPath = GetDirectoryPathFromUrl ( newFolderUrl ) ;
270303 if ( ! string . IsNullOrEmpty ( directoryPath ) )
271304 {
272305 // Need to upload an empty '.keep' blob because Azure Blob Storage does not support direct directory creation
@@ -402,6 +435,7 @@ public string GetAbsoluteUrl(string blobKey)
402435 private string [ ] GetOutlineFromUrl ( string url )
403436 {
404437 var relativeUrl = url ;
438+
405439 if ( url . IsAbsoluteUrl ( ) )
406440 {
407441 relativeUrl = Uri . UnescapeDataString ( new Uri ( url ) . AbsolutePath ) ;
@@ -419,13 +453,13 @@ private string GetContainerNameFromUrl(string url)
419453 private string GetDirectoryPathFromUrl ( string url )
420454 {
421455 var result = string . Join ( Delimiter , GetOutlineFromUrl ( url ) . Skip ( 1 ) . ToArray ( ) ) ;
422- return ! string . IsNullOrEmpty ( result ) ? result + Delimiter : null ;
456+ return ! string . IsNullOrEmpty ( result ) ? Uri . UnescapeDataString ( result ) + Delimiter : null ;
423457 }
424458
425459 private string GetFilePathFromUrl ( string url )
426460 {
427461 var result = string . Join ( Delimiter , GetOutlineFromUrl ( url ) . Skip ( 1 ) . ToArray ( ) ) ;
428- return ! string . IsNullOrEmpty ( result ) ? result : null ;
462+ return ! string . IsNullOrEmpty ( result ) ? Uri . UnescapeDataString ( result ) : null ;
429463 }
430464
431465 private string GetParentUrl ( string baseUri , string blobPrefix )
@@ -479,9 +513,13 @@ private BlobInfo ConvertBlobToBlobInfo(BlobClient blob, BlobProperties props)
479513
480514 private BlobInfo ConvertBlobToBlobInfo ( BlobItem blob , string baseUri )
481515 {
482- var fileName = Path . GetFileName ( blob . Name ) ;
483- var absoluteUrl = UrlHelperExtensions . Combine ( baseUri , EscapeUri ( blob . Name ) ) ;
516+ var fileUrlBuilder = new UriBuilder ( new Uri ( baseUri ) ) ;
517+ fileUrlBuilder . Path = fileUrlBuilder . Path + "/" + blob . Name ;
518+ var absoluteUrl = fileUrlBuilder . ToString ( ) ;
519+
484520 var relativeUrl = absoluteUrl . Replace ( EscapeUri ( _blobServiceClient . Uri . ToString ( ) ) , string . Empty ) ;
521+
522+ var fileName = Path . GetFileName ( blob . Name ) ;
485523 var contentType = MimeTypeResolver . ResolveContentType ( fileName ) ;
486524
487525 return new BlobInfo
0 commit comments