2018-06-29 19:52:40 +02:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Threading.Tasks ;
using Umbraco.Core.Configuration.UmbracoSettings ;
using Umbraco.Core.Logging ;
using Umbraco.Core.Models ;
namespace Umbraco.Core.IO
{
/// <summary>
/// A custom file system provider for media
/// </summary>
2018-10-26 15:06:53 +02:00
public class MediaFileSystem : FileSystemWrapper , IMediaFileSystem
2018-06-29 19:52:40 +02:00
{
2018-11-24 15:38:00 +01:00
private readonly IMediaPathScheme _mediaPathScheme ;
private readonly IContentSection _contentConfig ;
private readonly ILogger _logger ;
2018-10-26 15:06:53 +02:00
/// <summary>
/// Initializes a new instance of the <see cref="MediaFileSystem"/> class.
/// </summary>
2018-11-24 15:38:00 +01:00
public MediaFileSystem ( IFileSystem innerFileSystem , IContentSection contentConfig , IMediaPathScheme mediaPathScheme , ILogger logger )
2018-10-26 15:06:53 +02:00
: base ( innerFileSystem )
2018-06-29 19:52:40 +02:00
{
2018-11-24 15:38:00 +01:00
_contentConfig = contentConfig ;
_mediaPathScheme = mediaPathScheme ;
_logger = logger ;
2018-06-29 19:52:40 +02:00
}
2018-10-26 15:06:53 +02:00
/// <inheritoc />
2018-06-29 19:52:40 +02:00
public void DeleteMediaFiles ( IEnumerable < string > files )
{
files = files . Distinct ( ) ;
2018-10-26 15:06:53 +02:00
// kinda try to keep things under control
var options = new ParallelOptions { MaxDegreeOfParallelism = 20 } ;
Parallel . ForEach ( files , options , file = >
2018-06-29 19:52:40 +02:00
{
try
{
if ( file . IsNullOrWhiteSpace ( ) ) return ;
if ( FileExists ( file ) = = false ) return ;
DeleteFile ( file ) ;
2018-11-24 15:38:00 +01:00
var directory = _mediaPathScheme . GetDeleteDirectory ( this , file ) ;
2018-06-20 10:49:12 +02:00
if ( ! directory . IsNullOrWhiteSpace ( ) )
2018-06-29 19:52:40 +02:00
DeleteDirectory ( directory , true ) ;
}
catch ( Exception e )
{
2018-11-24 15:38:00 +01:00
_logger . Error < MediaFileSystem > ( e , "Failed to delete media file '{File}'." , file ) ;
2018-06-29 19:52:40 +02:00
}
} ) ;
}
#region Media Path
2018-10-26 15:06:53 +02:00
/// <inheritoc />
2018-06-29 19:52:40 +02:00
public string GetMediaPath ( string filename , Guid cuid , Guid puid )
{
filename = Path . GetFileName ( filename ) ;
if ( filename = = null ) throw new ArgumentException ( "Cannot become a safe filename." , nameof ( filename ) ) ;
filename = IOHelper . SafeFileName ( filename . ToLowerInvariant ( ) ) ;
2018-11-24 15:38:00 +01:00
return _mediaPathScheme . GetFilePath ( this , cuid , puid , filename ) ;
2018-06-29 19:52:40 +02:00
}
2018-10-26 15:06:53 +02:00
/// <inheritoc />
2018-06-29 19:52:40 +02:00
public string GetMediaPath ( string filename , string prevpath , Guid cuid , Guid puid )
{
filename = Path . GetFileName ( filename ) ;
if ( filename = = null ) throw new ArgumentException ( "Cannot become a safe filename." , nameof ( filename ) ) ;
filename = IOHelper . SafeFileName ( filename . ToLowerInvariant ( ) ) ;
2018-11-24 15:38:00 +01:00
return _mediaPathScheme . GetFilePath ( this , cuid , puid , filename , prevpath ) ;
2018-06-29 19:52:40 +02:00
}
#endregion
#region Associated Media Files
2018-10-26 15:06:53 +02:00
/// <inheritoc />
2018-06-29 19:52:40 +02:00
public string StoreFile ( IContentBase content , PropertyType propertyType , string filename , Stream filestream , string oldpath )
{
if ( content = = null ) throw new ArgumentNullException ( nameof ( content ) ) ;
if ( propertyType = = null ) throw new ArgumentNullException ( nameof ( propertyType ) ) ;
2019-10-07 22:10:21 +02:00
if ( filename = = null ) throw new ArgumentNullException ( nameof ( filename ) ) ;
if ( string . IsNullOrWhiteSpace ( filename ) ) throw new ArgumentException ( "Value can't be empty or consist only of white-space characters." , nameof ( filename ) ) ;
2018-06-29 19:52:40 +02:00
if ( filestream = = null ) throw new ArgumentNullException ( nameof ( filestream ) ) ;
// clear the old file, if any
if ( string . IsNullOrWhiteSpace ( oldpath ) = = false )
DeleteFile ( oldpath ) ;
// get the filepath, store the data
// use oldpath as "prevpath" to try and reuse the folder, in original number-based scheme
var filepath = GetMediaPath ( filename , oldpath , content . Key , propertyType . Key ) ;
AddFile ( filepath , filestream ) ;
return filepath ;
}
2018-10-26 15:06:53 +02:00
/// <inheritoc />
2018-06-29 19:52:40 +02:00
public string CopyFile ( IContentBase content , PropertyType propertyType , string sourcepath )
{
if ( content = = null ) throw new ArgumentNullException ( nameof ( content ) ) ;
if ( propertyType = = null ) throw new ArgumentNullException ( nameof ( propertyType ) ) ;
2019-10-07 22:10:21 +02:00
if ( sourcepath = = null ) throw new ArgumentNullException ( nameof ( sourcepath ) ) ;
if ( string . IsNullOrWhiteSpace ( sourcepath ) ) throw new ArgumentException ( "Value can't be empty or consist only of white-space characters." , nameof ( sourcepath ) ) ;
2018-06-29 19:52:40 +02:00
// ensure we have a file to copy
if ( FileExists ( sourcepath ) = = false ) return null ;
// get the filepath
var filename = Path . GetFileName ( sourcepath ) ;
var filepath = GetMediaPath ( filename , content . Key , propertyType . Key ) ;
this . CopyFile ( sourcepath , filepath ) ;
return filepath ;
}
2018-11-24 15:38:00 +01:00
#endregion
2018-06-29 19:52:40 +02:00
}
}