using System; using System.Globalization; using System.IO; using System.Threading; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; namespace Umbraco.Core.IO.MediaPathSchemes { /// /// Implements the original media path scheme. /// /// /// Path is "{number}/{filename}" or "{number}-{filename}" where number is an incremented counter. /// Use '/' or '-' depending on UploadAllowDirectories setting. /// // scheme: path is "/" where number is an incremented counter public class OriginalMediaPathScheme : IMediaPathScheme { private readonly object _folderCounterLock = new object(); private long _folderCounter; private bool _folderCounterInitialized; /// public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null) { string directory; if (previous != null) { // old scheme, with a previous path // prevpath should be "/" OR "-" // and we want to reuse the "" part, so try to find it const string sep = "/"; var pos = previous.IndexOf(sep, StringComparison.Ordinal); var s = pos > 0 ? previous.Substring(0, pos) : null; directory = pos > 0 && int.TryParse(s, out _) ? s : GetNextDirectory(fileSystem); } else { directory = GetNextDirectory(fileSystem); } if (directory == null) throw new InvalidOperationException("Cannot use a null directory."); return Path.Combine(directory, filename).Replace('\\', '/'); } /// public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath) { return Path.GetDirectoryName(filepath); } private string GetNextDirectory(IFileSystem fileSystem) { EnsureFolderCounterIsInitialized(fileSystem); return Interlocked.Increment(ref _folderCounter).ToString(CultureInfo.InvariantCulture); } private void EnsureFolderCounterIsInitialized(IFileSystem fileSystem) { lock (_folderCounterLock) { if (_folderCounterInitialized) return; _folderCounter = 1000; // seed var directories = fileSystem.GetDirectories(""); foreach (var directory in directories) { if (long.TryParse(directory, out var folderNumber) && folderNumber > _folderCounter) _folderCounter = folderNumber; } // note: not multi-domains ie LB safe as another domain could create directories // while we read and parse them - don't fix, move to new scheme eventually _folderCounterInitialized = true; } } } }