Exemple #1
0
        private async Task <(bool Valid, bool NameChanged, MediaPathData DestPathData)> ValidateMoveOperation(
            MediaFile file,
            string destinationFileName,
            DuplicateFileHandling dupeFileHandling)
        {
            Guard.NotNull(file, nameof(file));
            Guard.NotEmpty(destinationFileName, nameof(destinationFileName));

            var destPathData  = CreateDestinationPathData(file, destinationFileName);
            var destFileName  = destPathData.FileName;
            var destFolderId  = destPathData.Folder.Id;
            var folderChanged = destFolderId != file.FolderId;
            var shouldRestore = false;

            var nameChanged = !destFileName.EqualsNoCase(file.Name);

            if (file.FolderId.HasValue && folderChanged)
            {
                // When "Move" operation: ensure file stays in source album.
                ValidateAlbums("Move", file.FolderId.Value, destFolderId);
            }

            if (nameChanged)
            {
                // Ensure both MIME types are equal
                ValidateMimeTypes("Move", file.MimeType, destPathData.MimeType);
            }

            // Check whether destination file exists
            if (!folderChanged && file.Deleted)
            {
                // Special case where a file is moved from trash to its origin location.
                // In this case the file should just be restored without any dupe check.
                shouldRestore = true;
            }
            else
            {
                var dupe = await _db.MediaFiles.FirstOrDefaultAsync(x => x.Name == destFileName && x.FolderId == destFolderId);

                if (dupe != null)
                {
                    if (!folderChanged)
                    {
                        throw _exceptionFactory.IdenticalPaths(ConvertMediaFile(file, destPathData.Folder));
                    }

                    switch (dupeFileHandling)
                    {
                    case DuplicateFileHandling.ThrowError:
                        var fullPath = destPathData.FullPath;
                        _helper.CheckUniqueFileName(destPathData.FileTitle, destPathData.Extension, dupe.Name, out _);
                        throw _exceptionFactory.DuplicateFile(fullPath, ConvertMediaFile(dupe, destPathData.Folder), destPathData.FullPath);

                    case DuplicateFileHandling.Rename:
                        if (_helper.CheckUniqueFileName(destPathData.FileTitle, destPathData.Extension, dupe.Name, out var uniqueName))
                        {
                            nameChanged           = true;
                            destPathData.FileName = uniqueName;
                            return(true, nameChanged, destPathData);
                        }
                        break;

                    case DuplicateFileHandling.Overwrite:
                        await DeleteFileAsync(dupe, true);

                        break;
                    }
                }
            }

            return(folderChanged || nameChanged || shouldRestore, nameChanged, destPathData);
        }
Exemple #2
0
 public MediaFileInfo ConvertMediaFile(MediaFile file)
 {
     return(ConvertMediaFile(file, _folderService.FindNode(file)?.Value));
 }
Exemple #3
0
        private async Task <(MediaFile Copy, bool IsDupe)> InternalCopyFile(
            MediaFile file,
            MediaPathData destPathData,
            bool copyData,
            DuplicateEntryHandling dupeEntryHandling,
            Func <Task <MediaFile> > dupeFileSelector,
            Func <MediaPathData, Task> uniqueFileNameChecker)
        {
            // Find dupe and handle
            var isDupe = false;

            var dupe = await dupeFileSelector();

            if (dupe != null)
            {
                switch (dupeEntryHandling)
                {
                case DuplicateEntryHandling.Skip:
                    await uniqueFileNameChecker(destPathData);

                    return(dupe, true);

                case DuplicateEntryHandling.ThrowError:
                    var fullPath = destPathData.FullPath;
                    await uniqueFileNameChecker(destPathData);

                    throw _exceptionFactory.DuplicateFile(fullPath, ConvertMediaFile(dupe), destPathData.FullPath);

                case DuplicateEntryHandling.Rename:
                    await uniqueFileNameChecker(destPathData);

                    dupe = null;
                    break;

                case DuplicateEntryHandling.Overwrite:
                    if (file.FolderId == destPathData.Folder.Id)
                    {
                        throw new IOException(T("Admin.Media.Exception.Overwrite"));
                    }
                    break;
                }
            }

            isDupe = dupe != null;
            var copy = dupe ?? new MediaFile();

            // Simple clone
            MapMediaFile(file, copy);

            // Set folder id
            copy.FolderId = destPathData.Folder.Id;

            // A copied file cannot stay in deleted state
            copy.Deleted = false;

            // Set name stuff
            if (!copy.Name.EqualsNoCase(destPathData.FileName))
            {
                copy.Name      = destPathData.FileName;
                copy.Extension = destPathData.Extension;
                copy.MimeType  = destPathData.MimeType;
            }

            // Save to DB
            if (isDupe)
            {
                _db.TryUpdate(copy);
            }
            else
            {
                _db.MediaFiles.Add(copy);
            }

            // Copy data: blob, alt, title etc.
            if (copyData)
            {
                await InternalCopyFileData(file, copy);
            }

            return(copy, isDupe);
        }
Exemple #4
0
        protected async Task <(MediaStorageItem StorageItem, MediaFile File)> ProcessFile(
            MediaFile file,
            MediaPathData pathData,
            Stream inStream,
            bool isTransient = true,
            DuplicateFileHandling dupeFileHandling = DuplicateFileHandling.ThrowError,
            MimeValidationType mediaValidationType = MimeValidationType.MimeTypeMustMatch)
        {
            if (file != null)
            {
                if (dupeFileHandling == DuplicateFileHandling.ThrowError)
                {
                    var fullPath = pathData.FullPath;
                    await CheckUniqueFileName(pathData);

                    throw _exceptionFactory.DuplicateFile(fullPath, ConvertMediaFile(file, pathData.Folder), pathData.FullPath);
                }
                else if (dupeFileHandling == DuplicateFileHandling.Rename)
                {
                    if (await CheckUniqueFileName(pathData))
                    {
                        file = null;
                    }
                }
            }

            if (file != null && mediaValidationType != MimeValidationType.NoValidation)
            {
                if (mediaValidationType == MimeValidationType.MimeTypeMustMatch)
                {
                    ValidateMimeTypes("Save", file.MimeType, pathData.MimeType);
                }
                else if (mediaValidationType == MimeValidationType.MediaTypeMustMatch)
                {
                    ValidateMediaTypes("Save", _typeResolver.Resolve(pathData.Extension), file.MediaType);
                }

                // Restore file if soft-deleted
                file.Deleted = false;

                // Delete thumbnail
                await _imageCache.DeleteAsync(file);
            }

            file ??= new MediaFile
            {
                IsTransient = isTransient,
                FolderId    = pathData.Node.Value.Id
            };

            // Untrackable folders can never contain transient files.
            if (!pathData.Folder.CanDetectTracks)
            {
                file.IsTransient = false;
            }

            var name = pathData.FileName;

            if (name != pathData.FileName)
            {
                pathData.FileName = name;
            }

            file.Name      = pathData.FileName;
            file.Extension = pathData.Extension;
            file.MimeType  = pathData.MimeType;
            if (file.MediaType == null)
            {
                file.MediaType = _typeResolver.Resolve(pathData.Extension, pathData.MimeType);
            }

            // Process image
            if (inStream != null && inStream.Length > 0 && file.MediaType == MediaType.Image && (await ProcessImage(file, inStream)).Out(out var outImage))
            {
                file.Width     = outImage.Width;
                file.Height    = outImage.Height;
                file.PixelSize = outImage.Width * outImage.Height;

                return(MediaStorageItem.FromImage(outImage), file);
            }
            else
            {
                file.RefreshMetadata(inStream, _imageProcessor.Factory);

                return(MediaStorageItem.FromStream(inStream), file);
            }
        }
Exemple #5
0
        public bool FindEqualFile(Stream source, IEnumerable <MediaFile> files, bool leaveOpen, out MediaFile equalFile)
        {
            Guard.NotNull(source, nameof(source));
            Guard.NotNull(files, nameof(files));

            equalFile = null;

            try
            {
                foreach (var file in files)
                {
                    source.Seek(0, SeekOrigin.Begin);

                    using (var other = _storageProvider.OpenRead(file))
                    {
                        if (source.ContentsEqual(other, true))
                        {
                            equalFile = file;
                            return(true);
                        }
                    }
                }

                return(false);
            }
            catch
            {
                return(false);
            }
            finally
            {
                if (!leaveOpen)
                {
                    source.Dispose();
                }
            }
        }
        /// <summary>
        /// Tries to find an equal file by comparing the source buffer to a list of files.
        /// </summary>
        /// <param name="source">Binary source file data to find a match for.</param>
        /// <param name="files">The sequence of files to seek within for duplicates.</param>
        /// <param name="equalFile">A file from the <paramref name="files"/> collection whose content is equal to <paramref name="sourceBuffer"/>.</param>
        /// <returns>The passed file binary when no file equals in the sequence, <c>null</c> otherwise.</returns>
        public static byte[] FindEqualFile(this IMediaService service, byte[] sourceBuffer, IEnumerable <MediaFile> files, out MediaFile equalFile)
        {
            Guard.NotNull(sourceBuffer, nameof(sourceBuffer));

            if (!service.FindEqualFile(new MemoryStream(sourceBuffer), files, false, out equalFile))
            {
                return(sourceBuffer);
            }

            return(null);
        }
Exemple #7
0
 public static MediaType Resolve(this IMediaTypeResolver resolver, MediaFile file)
 {
     Guard.NotNull(file, nameof(file));
     return(resolver.Resolve(file.Extension, file.MimeType));
 }