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); }
public MediaFileInfo ConvertMediaFile(MediaFile file) { return(ConvertMediaFile(file, _folderService.FindNode(file)?.Value)); }
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); }
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); } }
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); }
public static MediaType Resolve(this IMediaTypeResolver resolver, MediaFile file) { Guard.NotNull(file, nameof(file)); return(resolver.Resolve(file.Extension, file.MimeType)); }