116 lines
4.3 KiB
C#
116 lines
4.3 KiB
C#
using FluentMigrator;
|
|
using Nop.Core.Domain.Media;
|
|
using Nop.Data;
|
|
using Nop.Data.Migrations;
|
|
using Nop.Services.Media;
|
|
using Nop.Services.Media.RoxyFileman;
|
|
|
|
namespace Nop.Web.Framework.Migrations.UpgradeTo460;
|
|
|
|
[NopMigration("2022-10-18 00:00:00", "Move uploaded images to disk", MigrationProcessType.Update)]
|
|
public class UploadedImagesMigration : Migration
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly IPictureService _pictureService;
|
|
protected readonly IRepository<Picture> _pictureRepository;
|
|
protected readonly IRoxyFilemanFileProvider _roxyFilemanFileProvider;
|
|
|
|
#endregion
|
|
|
|
public UploadedImagesMigration(IPictureService pictureService, IRepository<Picture> pictureRepository, IRoxyFilemanFileProvider roxyFilemanFileProvider)
|
|
{
|
|
_pictureService = pictureService;
|
|
_pictureRepository = pictureRepository;
|
|
_roxyFilemanFileProvider = roxyFilemanFileProvider;
|
|
}
|
|
|
|
public override void Up()
|
|
{
|
|
if (!_pictureService.IsStoreInDbAsync().Result)
|
|
return;
|
|
|
|
const int pageSize = 400;
|
|
var pageIndex = 0;
|
|
var uploadRoot = $"~{NopRoxyFilemanDefaults.DefaultRootDirectory}/";
|
|
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
var pictures = _pictureService.GetPicturesAsync(uploadRoot,
|
|
pageIndex, pageSize).Result;
|
|
pageIndex++;
|
|
|
|
//all pictures flushed?
|
|
if (!pictures.Any())
|
|
break;
|
|
|
|
foreach (var picture in pictures)
|
|
{
|
|
if (string.IsNullOrEmpty(picture?.VirtualPath) || string.IsNullOrEmpty(picture.SeoFilename))
|
|
return;
|
|
|
|
var seoFileName = picture.SeoFilename;
|
|
|
|
var lastPart = _pictureService.GetFileExtensionFromMimeTypeAsync(picture.MimeType).Result;
|
|
|
|
var thumbFileName = $"{seoFileName}.{lastPart}";
|
|
var thumbDirectoryName = picture.VirtualPath[uploadRoot.Length..];
|
|
var thumbFilePath = Path.Combine(thumbDirectoryName, thumbFileName);
|
|
|
|
_roxyFilemanFileProvider.CreateDirectory("/", thumbDirectoryName);
|
|
|
|
if (picture.IsNew)
|
|
{
|
|
// delete old file if exist
|
|
_roxyFilemanFileProvider.DeleteFile(thumbFilePath);
|
|
}
|
|
|
|
if (_roxyFilemanFileProvider.GetFileInfo(thumbFilePath).Exists)
|
|
{
|
|
_pictureRepository.DeleteAsync(picture, false).Wait();
|
|
continue;
|
|
}
|
|
//the named mutex helps to avoid creating the same files in different threads,
|
|
//and does not decrease performance significantly, because the code is blocked only for the specific file.
|
|
//you should be very careful, mutexes cannot be used in with the await operation
|
|
//we can't use semaphore here, because it produces PlatformNotSupportedException exception on UNIX based systems
|
|
using var mutex = new Mutex(false, thumbFileName);
|
|
|
|
mutex.WaitOne();
|
|
|
|
try
|
|
{
|
|
//check, if the file was created, while we were waiting for the release of the mutex.
|
|
if (!_roxyFilemanFileProvider.GetFileInfo(thumbFilePath).Exists)
|
|
{
|
|
var pictureBinary = _pictureService.LoadPictureBinaryAsync(picture).Result;
|
|
|
|
if (pictureBinary == null || pictureBinary.Length == 0)
|
|
continue;
|
|
|
|
using var stream = new MemoryStream(pictureBinary);
|
|
_roxyFilemanFileProvider.SaveFileAsync(thumbDirectoryName, thumbFileName, picture.MimeType, stream).Wait();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
mutex.ReleaseMutex();
|
|
}
|
|
|
|
_pictureRepository.DeleteAsync(picture, false).Wait();
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
public override void Down()
|
|
{
|
|
//add the downgrade logic if necessary
|
|
}
|
|
} |