2018-06-20 10:49:12 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Threading;
|
2018-12-12 17:49:24 +01:00
|
|
|
|
using Umbraco.Core.Composing;
|
2018-06-20 10:49:12 +02:00
|
|
|
|
using Umbraco.Core.Configuration;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Core.IO.MediaPathSchemes
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Implements the original media path scheme.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// <para>Path is "{number}/{filename}" or "{number}-{filename}" where number is an incremented counter.</para>
|
|
|
|
|
|
/// <para>Use '/' or '-' depending on UploadAllowDirectories setting.</para>
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
// scheme: path is "<number>/<filename>" where number is an incremented counter
|
|
|
|
|
|
public class OriginalMediaPathScheme : IMediaPathScheme
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly object _folderCounterLock = new object();
|
|
|
|
|
|
private long _folderCounter;
|
|
|
|
|
|
private bool _folderCounterInitialized;
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2018-11-24 15:38:00 +01:00
|
|
|
|
public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null)
|
2018-06-20 10:49:12 +02:00
|
|
|
|
{
|
|
|
|
|
|
string directory;
|
|
|
|
|
|
if (previous != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// old scheme, with a previous path
|
|
|
|
|
|
// prevpath should be "<int>/<filename>" OR "<int>-<filename>"
|
|
|
|
|
|
// and we want to reuse the "<int>" part, so try to find it
|
|
|
|
|
|
|
2019-01-30 23:42:25 +11:00
|
|
|
|
const string sep = "/";
|
2018-06-20 10:49:12 +02:00
|
|
|
|
var pos = previous.IndexOf(sep, StringComparison.Ordinal);
|
|
|
|
|
|
var s = pos > 0 ? previous.Substring(0, pos) : null;
|
|
|
|
|
|
|
2018-11-24 15:38:00 +01:00
|
|
|
|
directory = pos > 0 && int.TryParse(s, out _) ? s : GetNextDirectory(fileSystem);
|
2018-06-20 10:49:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2018-11-24 15:38:00 +01:00
|
|
|
|
directory = GetNextDirectory(fileSystem);
|
2018-06-20 10:49:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (directory == null)
|
|
|
|
|
|
throw new InvalidOperationException("Cannot use a null directory.");
|
|
|
|
|
|
|
2019-01-30 23:42:25 +11:00
|
|
|
|
return Path.Combine(directory, filename).Replace('\\', '/');
|
2018-06-20 10:49:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2018-11-24 15:38:00 +01:00
|
|
|
|
public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath)
|
2018-06-20 10:49:12 +02:00
|
|
|
|
{
|
|
|
|
|
|
return Path.GetDirectoryName(filepath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-24 15:38:00 +01:00
|
|
|
|
private string GetNextDirectory(IFileSystem fileSystem)
|
2018-06-20 10:49:12 +02:00
|
|
|
|
{
|
2018-11-24 15:38:00 +01:00
|
|
|
|
EnsureFolderCounterIsInitialized(fileSystem);
|
2018-06-20 10:49:12 +02:00
|
|
|
|
return Interlocked.Increment(ref _folderCounter).ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-24 15:38:00 +01:00
|
|
|
|
private void EnsureFolderCounterIsInitialized(IFileSystem fileSystem)
|
2018-06-20 10:49:12 +02:00
|
|
|
|
{
|
|
|
|
|
|
lock (_folderCounterLock)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_folderCounterInitialized) return;
|
|
|
|
|
|
|
|
|
|
|
|
_folderCounter = 1000; // seed
|
2018-11-24 15:38:00 +01:00
|
|
|
|
var directories = fileSystem.GetDirectories("");
|
2018-06-20 10:49:12 +02:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|