866 lines
24 KiB
C#
866 lines
24 KiB
C#
using EnVisage.Code;
|
|
using EnVisage.Code.BLL;
|
|
using EnVisage.Properties;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Web;
|
|
using System.Web.SessionState;
|
|
|
|
namespace EnVisage.Models
|
|
{
|
|
public class FileDescriptor
|
|
{
|
|
public Guid Id;
|
|
public Guid HolderId;
|
|
public AttachmentModel Meta;
|
|
public Stream Content;
|
|
}
|
|
|
|
public class FileManager : ManagerBase<Attachment, AttachmentModel>
|
|
{
|
|
public const string C_TEMPORARY_FILE_EXTENSION = ".tmp";
|
|
public const string C_PERMANENT_FILE_EXTENSION = ".file";
|
|
|
|
#region Constructors
|
|
|
|
public FileManager(EnVisageEntities dbContext)
|
|
: base(dbContext)
|
|
{
|
|
this.UserId = SecurityManager.GetUserPrincipal();
|
|
this.Init();
|
|
}
|
|
|
|
public FileManager(EnVisageEntities dbContext, Guid userId)
|
|
: base(dbContext)
|
|
{
|
|
this.UserId = userId;
|
|
this.Init();
|
|
}
|
|
|
|
public FileManager(EnVisageEntities dbContext, Guid userId, string permanentStorageDir)
|
|
: base(dbContext)
|
|
{
|
|
this.UserId = userId;
|
|
this.PermanentStoragePath = permanentStorageDir;
|
|
this.Init();
|
|
}
|
|
|
|
public FileManager(EnVisageEntities dbContext, Guid userId, string permanentStorageDir,
|
|
string tempStorageDir)
|
|
: base(dbContext)
|
|
{
|
|
this.UserId = userId;
|
|
this.PermanentStoragePath = permanentStorageDir;
|
|
this.TempStoragePath = tempStorageDir;
|
|
this.Init();
|
|
}
|
|
|
|
#endregion
|
|
#region User Folders
|
|
|
|
protected Guid userId = Guid.Empty;
|
|
|
|
public Guid UserId
|
|
{
|
|
get { return userId; }
|
|
set
|
|
{
|
|
if (value.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("User Id must be non empty");
|
|
|
|
userId = value;
|
|
}
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
if (String.IsNullOrEmpty(permStoragePath))
|
|
this.PermanentStoragePath = Settings.Default.AttachmentsPath;
|
|
|
|
if (String.IsNullOrEmpty(tempStoragePath))
|
|
{
|
|
if (!String.IsNullOrEmpty(Settings.Default.UploadTempPath))
|
|
this.TempStoragePath = Settings.Default.UploadTempPath;
|
|
else
|
|
SetDefaultTempDirectory();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
#region Temporary Storage
|
|
|
|
private Object sessionLock = new Object();
|
|
protected string tempStoragePath = String.Empty;
|
|
|
|
public string TempStoragePath
|
|
{
|
|
get { return tempStoragePath; }
|
|
set
|
|
{
|
|
if (String.IsNullOrEmpty(value))
|
|
throw new ArgumentNullException("Temporary files folder must be not empty");
|
|
|
|
string path = value;
|
|
|
|
if (VirtualPathUtility.IsAppRelative(value))
|
|
path = HttpContext.Current.Server.MapPath(value);
|
|
|
|
CheckFolderAccess(path, true);
|
|
tempStoragePath = path;
|
|
}
|
|
}
|
|
|
|
protected void SetDefaultTempDirectory()
|
|
{
|
|
tempStoragePath = permStoragePath;
|
|
}
|
|
|
|
protected void CheckFolderAccess(string path, bool createIfNotExists = false)
|
|
{
|
|
if (String.IsNullOrEmpty(path))
|
|
throw new ArgumentNullException("Path for check access is empty");
|
|
|
|
string errorMessage;
|
|
|
|
if (!Directory.Exists(path))
|
|
if (createIfNotExists)
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(path);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't create folder '{0}'", path);
|
|
throw new IOException(errorMessage, ex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errorMessage = String.Format("Folder '{0}' doesn't exist", path);
|
|
throw new IOException(errorMessage);
|
|
}
|
|
}
|
|
|
|
protected string GetTempFileName(Guid fileId)
|
|
{
|
|
string fileName = String.Format("{0}{1}", fileId.ToString("N"), C_TEMPORARY_FILE_EXTENSION);
|
|
return fileName;
|
|
}
|
|
|
|
protected string GetTempFilePath(string fileName)
|
|
{
|
|
string path = GetUserTempPath();
|
|
CheckFolderAccess(path, true);
|
|
|
|
path = String.Format("{0}\\{1}", path, fileName);
|
|
return path;
|
|
}
|
|
|
|
protected string GetUserTempPath()
|
|
{
|
|
string userFolder = userId.ToString("N");
|
|
string path = String.Format("{0}\\{1}", VirtualPathUtility.RemoveTrailingSlash(tempStoragePath),
|
|
userFolder);
|
|
|
|
return path;
|
|
}
|
|
|
|
public AttachmentModel CreateTempFile(HttpPostedFileBase file)
|
|
{
|
|
if (file == null)
|
|
throw new ArgumentNullException("Can't create temporary file for empty upload file");
|
|
|
|
string errorMessage;
|
|
|
|
Guid fileId = Guid.NewGuid();
|
|
string fileName = this.GetTempFileName(fileId);
|
|
string filePath = GetTempFilePath(fileName);
|
|
|
|
if (File.Exists(filePath))
|
|
{
|
|
errorMessage = String.Format("Name for new temporary file was generated, " +
|
|
"but file already was found in the storage (file name: {0})", filePath);
|
|
throw new IOException(errorMessage);
|
|
}
|
|
|
|
try
|
|
{
|
|
using (FileStream writableFile =
|
|
new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write))
|
|
{
|
|
// SA. ENV-958. Fix of file access errors with different processes
|
|
file.InputStream.CopyTo(writableFile);
|
|
writableFile.Flush();
|
|
writableFile.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't create temporary file. File path: {0}", filePath);
|
|
IOException exception = new IOException(errorMessage, ex);
|
|
throw exception;
|
|
}
|
|
|
|
AttachmentModel result = new AttachmentModel()
|
|
{
|
|
Id = fileId,
|
|
Name = file.FileName,
|
|
Size = file.ContentLength,
|
|
ContentType = file.ContentType,
|
|
IsNew = true
|
|
};
|
|
|
|
lock (sessionLock)
|
|
{
|
|
// Save file metadata to session
|
|
Dictionary<Guid, AttachmentModel> files =
|
|
HttpContext.Current.Session["TempFiles"] as Dictionary<Guid, AttachmentModel>;
|
|
|
|
if (files == null)
|
|
{
|
|
files = new Dictionary<Guid, AttachmentModel>();
|
|
HttpContext.Current.Session["TempFiles"] = files;
|
|
}
|
|
|
|
files.Add(fileId, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public void DeleteTempFile(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate and delete temporary file for empty identifier");
|
|
|
|
string errorMessage;
|
|
string fileName = this.GetTempFileName(fileId);
|
|
string filePath = GetTempFilePath(fileName);
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
errorMessage = String.Format("Can't delete temporary file '{0}'. File not found", filePath);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
lock (sessionLock)
|
|
{
|
|
// Delete file metadata from session
|
|
Dictionary<Guid, AttachmentModel> files =
|
|
HttpContext.Current.Session["TempFiles"] as Dictionary<Guid, AttachmentModel>;
|
|
|
|
if ((files != null) && files.ContainsKey(fileId))
|
|
files.Remove(fileId);
|
|
}
|
|
|
|
try
|
|
{
|
|
File.Delete(filePath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't delete temporary file '{0}'", filePath);
|
|
throw new IOException(errorMessage, ex);
|
|
}
|
|
}
|
|
|
|
public void DeleteTempFiles(IList<Guid> files, bool silent = false)
|
|
{
|
|
if (files == null)
|
|
throw new ArgumentNullException("The list of temporary files to delete is null");
|
|
|
|
foreach (Guid fileId in files)
|
|
try
|
|
{
|
|
this.DeleteTempFile(fileId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (!silent)
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
public bool MoveToPermanentStorage(Guid fileId, Guid holderId, System.Type holderType)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate temporary file for empty identifier");
|
|
|
|
if (holderId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't move temporary file to permanent storage. File holder ID is empty");
|
|
|
|
if (holderType == null)
|
|
throw new ArgumentNullException("Can't move temporary file to permanent storage. File holder TYPE is not specified");
|
|
|
|
bool tmpFileDeleted = true;
|
|
string errorMessage;
|
|
string tmpFileName = this.GetTempFileName(fileId);
|
|
string tmpFilePath = GetTempFilePath(tmpFileName);
|
|
|
|
if (!File.Exists(tmpFilePath))
|
|
{
|
|
errorMessage = String.Format("Can't move temporary file '{0}' to permanent storage. File not found", tmpFilePath);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
// Check there is no record for this file in the database
|
|
int foundRecordsCount = DbContext.Attachments.Where(x => x.Id.Equals(fileId)).Count();
|
|
|
|
if (foundRecordsCount > 0)
|
|
{
|
|
errorMessage = String.Format("Can't move temporary file '{0}' to permanent storage. Attachment already exists", tmpFilePath);
|
|
throw new Exception(errorMessage);
|
|
}
|
|
|
|
// Get metadata from session
|
|
Dictionary<Guid, AttachmentModel> files =
|
|
HttpContext.Current.Session["TempFiles"] as Dictionary<Guid, AttachmentModel>;
|
|
|
|
if ((files == null) || !files.ContainsKey(fileId))
|
|
{
|
|
errorMessage = String.Format("Can't move temporary file '{0}' to permanent storage. File metadata not found", tmpFilePath);
|
|
throw new Exception(errorMessage);
|
|
}
|
|
|
|
string newFileName = GetPermanentFileName(fileId);
|
|
string newFilePath = GetPermanentFilePath(newFileName);
|
|
|
|
try
|
|
{
|
|
using (FileStream inputFile =
|
|
new FileStream(tmpFilePath, FileMode.Open, FileAccess.Read, FileShare.Delete))
|
|
{
|
|
using (FileStream outputFile =
|
|
new FileStream(newFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
|
{
|
|
inputFile.CopyTo(outputFile);
|
|
outputFile.Flush();
|
|
outputFile.Close();
|
|
}
|
|
inputFile.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't copy temporary file '{0}' to permanent storage file '{1}'",
|
|
tmpFilePath, newFilePath);
|
|
throw new IOException(errorMessage, ex);
|
|
}
|
|
|
|
// Save descriptor to DB
|
|
AttachmentModel fileDescriptor = files[fileId];
|
|
Attachment newRec = new Attachment();
|
|
|
|
fileDescriptor.CopyTo(newRec);
|
|
newRec.ParentId = holderId;
|
|
newRec.ParentType = holderType.FullName;
|
|
newRec.FileName = newFilePath;
|
|
newRec.Created = DateTime.UtcNow;
|
|
DbContext.Attachments.Add(newRec);
|
|
|
|
// Delete file metadata from session
|
|
if ((files != null) && files.ContainsKey(fileId))
|
|
files.Remove(fileId);
|
|
|
|
try
|
|
{
|
|
File.Delete(tmpFilePath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
tmpFileDeleted = false;
|
|
}
|
|
|
|
return tmpFileDeleted;
|
|
}
|
|
|
|
public IList<Guid> MoveToPermanentStorage(IList<AttachmentModel> files, Guid holderId, System.Type holderType)
|
|
{
|
|
if (files == null)
|
|
throw new ArgumentNullException("The list of temporary files to move to permanent storage is null");
|
|
|
|
// TODO: First check all files can be moved
|
|
List<Guid> undeletedTempFiles = new List<Guid>();
|
|
|
|
foreach (AttachmentModel model in files)
|
|
{
|
|
bool deleted = MoveToPermanentStorage(model.Id, holderId, holderType);
|
|
|
|
if (!deleted)
|
|
undeletedTempFiles.Add(model.Id);
|
|
}
|
|
|
|
return undeletedTempFiles;
|
|
}
|
|
|
|
public FileDescriptor GetTempFileContent(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate temporary file for empty identifier");
|
|
|
|
string errorMessage;
|
|
FileDescriptor descriptor = new FileDescriptor()
|
|
{
|
|
Id = fileId
|
|
};
|
|
|
|
string fileName = this.GetTempFileName(fileId);
|
|
string filePath = GetTempFilePath(fileName);
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
errorMessage = String.Format("Temporary file '{0}' not found in the temporary storage", filePath);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
try
|
|
{
|
|
descriptor.Content = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't read temporary file '{0}' content", filePath);
|
|
Exception exception = new IOException(errorMessage, ex);
|
|
throw exception;
|
|
}
|
|
|
|
lock (sessionLock)
|
|
{
|
|
// Get file metadata
|
|
string contentType = String.Empty;
|
|
|
|
Dictionary<Guid, AttachmentModel> files =
|
|
HttpContext.Current.Session["TempFiles"] as Dictionary<Guid, AttachmentModel>;
|
|
|
|
if ((files != null) && files.ContainsKey(fileId))
|
|
descriptor.Meta = files[fileId];
|
|
}
|
|
|
|
return descriptor;
|
|
}
|
|
|
|
public void EmptyUserTempFolder()
|
|
{
|
|
string path = GetUserTempPath();
|
|
CheckFolderAccess(path, true);
|
|
|
|
// Delete all temporary files in user folder
|
|
string fileMask = String.Format("*{0}", C_TEMPORARY_FILE_EXTENSION);
|
|
string[] foundTempFiles = Directory.GetFiles(path, fileMask);
|
|
|
|
foreach (string fileName in foundTempFiles)
|
|
try
|
|
{
|
|
File.Delete(fileName);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
lock (sessionLock)
|
|
{
|
|
if (HttpContext.Current.Session["TempFiles"] != null)
|
|
HttpContext.Current.Session["TempFiles"] = null;
|
|
}
|
|
}
|
|
|
|
public bool IsTempFile(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate temporary file for empty identifier");
|
|
|
|
string fileName = this.GetTempFileName(fileId);
|
|
string filePath = GetTempFilePath(fileName);
|
|
return File.Exists(filePath);
|
|
}
|
|
|
|
#endregion
|
|
#region Permanent Storage
|
|
|
|
protected string permStoragePath = String.Empty;
|
|
|
|
public string PermanentStoragePath
|
|
{
|
|
get { return permStoragePath; }
|
|
set
|
|
{
|
|
if (String.IsNullOrEmpty(value))
|
|
throw new ArgumentNullException("Permanent files storage folder must be non-empty");
|
|
|
|
string path = value;
|
|
|
|
if (VirtualPathUtility.IsAppRelative(value))
|
|
path = HttpContext.Current.Server.MapPath(value);
|
|
|
|
CheckFolderAccess(path, true);
|
|
permStoragePath = path;
|
|
}
|
|
}
|
|
|
|
protected string GetPermanentFileName(Guid fileId)
|
|
{
|
|
string fileName = String.Format("{0}{1}", fileId.ToString("N"), C_PERMANENT_FILE_EXTENSION);
|
|
return fileName;
|
|
}
|
|
|
|
protected string GetPermanentFilePath(string fileName)
|
|
{
|
|
string path = GetUserPermanentPath();
|
|
CheckFolderAccess(path, true);
|
|
|
|
path = String.Format("{0}\\{1}", path, fileName);
|
|
return path;
|
|
}
|
|
|
|
protected string GetUserPermanentPath()
|
|
{
|
|
string userFolder = userId.ToString("N");
|
|
string path = String.Format("{0}\\{1}", VirtualPathUtility.RemoveTrailingSlash(permStoragePath),
|
|
userFolder);
|
|
|
|
return path;
|
|
}
|
|
|
|
public FileDescriptor GetPermanentFileContent(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate and permanent file for empty identifier");
|
|
|
|
string errorMessage;
|
|
var foundAttachments = DbContext.Attachments.Where(x=>x.Id.Equals(fileId));
|
|
|
|
if (foundAttachments.Count() < 1)
|
|
{
|
|
errorMessage = String.Format("File not found in permanent storage (Id = '{0}')", fileId.ToString());
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
Attachment dbRecord = foundAttachments.First();
|
|
FileDescriptor descriptor = new FileDescriptor()
|
|
{
|
|
Id = fileId,
|
|
HolderId = dbRecord.ParentId,
|
|
};
|
|
|
|
AttachmentModel model = (AttachmentModel)dbRecord;
|
|
descriptor.Meta = model;
|
|
string filePath = dbRecord.FileName;
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
errorMessage = String.Format("File '{0}' not found in permanent storage", filePath);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
try
|
|
{
|
|
descriptor.Content = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't read file '{0}' content in permanent storage", filePath);
|
|
Exception exception = new IOException(errorMessage, ex);
|
|
throw exception;
|
|
}
|
|
|
|
return descriptor;
|
|
}
|
|
|
|
public void DeletePermanentFile(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate and delete permanent file for empty identifier");
|
|
|
|
string errorMessage;
|
|
string fileName = this.GetPermanentFileName(fileId);
|
|
string filePath = GetPermanentFilePath(fileName);
|
|
|
|
// Delete file metadata from database
|
|
var filesToDelete = DbContext.Attachments.Where(x => x.Id.Equals(fileId));
|
|
DbContext.Attachments.RemoveRange(filesToDelete);
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
errorMessage = String.Format("Can't delete file '{0}' from permanent storage. File not found", filePath);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
try
|
|
{
|
|
File.Delete(filePath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't delete file '{0}' from permanent storage", filePath);
|
|
throw new IOException(errorMessage, ex);
|
|
}
|
|
}
|
|
|
|
public void DeletePermanentFiles(IEnumerable<Guid> files, bool silent = false)
|
|
{
|
|
if (files == null)
|
|
throw new ArgumentNullException("The list of permanent files to delete is null");
|
|
|
|
// TODO: First check all files can be deleted
|
|
|
|
foreach (Guid fileId in files)
|
|
try
|
|
{
|
|
this.DeletePermanentFile(fileId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (!silent)
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
public bool IsPermanentFile(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate permanent storage file for empty identifier");
|
|
|
|
int itemsCount = DbContext.Attachments.Where(x => x.Id.Equals(fileId)).Count();
|
|
return itemsCount > 0;
|
|
}
|
|
|
|
public IList<Guid> GetPermanentFilesByHolder(Guid holderId, System.Type holderType = null)
|
|
{
|
|
return this.GetPermanentFilesByHolder(new List<Guid>() { holderId }, holderType);
|
|
}
|
|
|
|
public IList<Guid> GetPermanentFilesByHolder(IEnumerable<Guid> holderIds, System.Type holderType = null)
|
|
{
|
|
List<Guid> attachs;
|
|
|
|
if (holderType != null)
|
|
attachs = DbContext.Attachments.Where(x => holderIds.Contains(x.ParentId) &&
|
|
x.ParentType.Equals(holderType.FullName)).Select(y => y.Id).ToList();
|
|
else
|
|
attachs = DbContext.Attachments.Where(x => holderIds.Contains(x.ParentId))
|
|
.Select(y => y.Id).ToList();
|
|
|
|
return attachs;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Changes parent for existing permanent file
|
|
/// </summary>
|
|
/// <param name="permanentFileId">Id of the file</param>
|
|
/// <param name="newParentId">New parent Id or Guid.Empty for no change</param>
|
|
/// <param name="newParentType">New parent type or null for no change</param>
|
|
public void ChangeFileParent(Guid permanentFileId, Guid newParentId, System.Type newParentType = null)
|
|
{
|
|
if (permanentFileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate permanent storage file for empty identifier");
|
|
|
|
var attachment = DbContext.Attachments.FirstOrDefault(x => x.Id.Equals(permanentFileId));
|
|
|
|
if ((attachment == null) || (attachment.Id.Equals(Guid.Empty)))
|
|
{
|
|
string errorMessage = String.Format("Can't change parent for file '{0}'. File not found", permanentFileId);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
if (!newParentId.Equals(Guid.Empty) && !attachment.ParentId.Equals(newParentId))
|
|
{
|
|
attachment.ParentId = newParentId;
|
|
}
|
|
|
|
if (newParentType != null)
|
|
{
|
|
string newParentTypeName = newParentType.FullName;
|
|
|
|
if (attachment.ParentType != newParentTypeName)
|
|
attachment.ParentType = newParentTypeName;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Changes parent for a group of existing of permanent files
|
|
/// </summary>
|
|
/// <param name="permanentFiles">List of file models</param>
|
|
/// <param name="newParentId">New parent Id or Guid.Empty for no change</param>
|
|
/// <param name="newParentType">New parent type or null for no change</param>
|
|
public void ChangeFilesParent(IList<AttachmentModel> permanentFiles, Guid newParentId, System.Type newParentType = null)
|
|
{
|
|
if (permanentFiles == null)
|
|
throw new ArgumentNullException("List of permanent storage files must be not null");
|
|
|
|
foreach (AttachmentModel fileModel in permanentFiles)
|
|
this.ChangeFileParent(fileModel.Id, newParentId, newParentType);
|
|
}
|
|
|
|
public AttachmentModel CopyPermanentFile(Guid fileId, Guid newHolderId, System.Type newHolderType)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate permanent file for empty identifier");
|
|
|
|
if (newHolderId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't copy permanent file. File new holder ID is empty");
|
|
|
|
if (newHolderType == null)
|
|
throw new ArgumentNullException("Can't copy permanent file. File new holder TYPE is not specified");
|
|
|
|
string errorMessage;
|
|
var sourceFileMeta = DbContext.Attachments.FirstOrDefault(x => x.Id.Equals(fileId));
|
|
|
|
if ((sourceFileMeta == null) || sourceFileMeta.Id.Equals(Guid.Empty))
|
|
{
|
|
errorMessage = String.Format("Can't copy permanent file '{0}'. File not found", fileId);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
string sourceFilePath = sourceFileMeta.FileName;
|
|
|
|
if (!File.Exists(sourceFilePath))
|
|
{
|
|
errorMessage = String.Format("Can't copy permanent file '{0}'. File not found", sourceFilePath);
|
|
throw new FileNotFoundException(errorMessage);
|
|
}
|
|
|
|
Guid newFileId = Guid.NewGuid();
|
|
string newFileName = GetPermanentFileName(newFileId);
|
|
string newFilePath = GetPermanentFilePath(newFileName);
|
|
|
|
try
|
|
{
|
|
using (FileStream inputFile =
|
|
new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Delete))
|
|
{
|
|
using (FileStream outputFile =
|
|
new FileStream(newFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
|
{
|
|
inputFile.CopyTo(outputFile);
|
|
outputFile.Flush();
|
|
outputFile.Close();
|
|
}
|
|
inputFile.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = String.Format("Can't copy permanent file '{0}' to '{1}'", sourceFilePath, newFilePath);
|
|
throw new IOException(errorMessage, ex);
|
|
}
|
|
|
|
// Save descriptor to DB
|
|
Attachment newRec = new Attachment()
|
|
{
|
|
Id = newFileId,
|
|
ContentType = sourceFileMeta.ContentType,
|
|
Created = DateTime.UtcNow,
|
|
SourceFileName = sourceFileMeta.SourceFileName,
|
|
FileSize = sourceFileMeta.FileSize,
|
|
ParentId = newHolderId,
|
|
ParentType = newHolderType.FullName,
|
|
FileName = newFilePath
|
|
};
|
|
|
|
DbContext.Attachments.Add(newRec);
|
|
AttachmentModel newFileModel = (AttachmentModel)newRec;
|
|
|
|
return newFileModel;
|
|
}
|
|
|
|
public IList<AttachmentModel> CopyPermanentFiles(IList<AttachmentModel> files, Guid newHolderId, System.Type newHolderType)
|
|
{
|
|
if (files == null)
|
|
throw new ArgumentNullException("The list of permanent files to copy is null");
|
|
|
|
// TODO: First check all files can be moved
|
|
List<AttachmentModel> newModels = new List<AttachmentModel>();
|
|
|
|
foreach (AttachmentModel model in files)
|
|
{
|
|
AttachmentModel newFileModel = CopyPermanentFile(model.Id, newHolderId, newHolderType);
|
|
newModels.Add(newFileModel);
|
|
}
|
|
|
|
return newModels;
|
|
}
|
|
|
|
// SA: Don't delete. Writed for future functionality
|
|
//public void DeleteUserUnattachedPermanentFiles()
|
|
//{
|
|
// // Remove attachments, that have no parent object
|
|
// var unattachedFiles = DbContext.BLL_UnattachedFiles.AsNoTracking().Select(x=>x.Id).ToList();
|
|
// this.DeletePermanentFiles(unattachedFiles, true);
|
|
// unattachedFiles = null;
|
|
|
|
// // Remove permanent files, that have no corresponding database records
|
|
// var registeredFiles = DbContext.Attachments.AsNoTracking().Select(x => x.FileName).ToList();
|
|
|
|
// string fileMask = String.Format("*{0}", C_PERMANENT_FILE_EXTENSION);
|
|
// string userPath = this.GetUserPermanentPath();
|
|
// string[] foundTempFiles = Directory.GetFiles(userPath, fileMask);
|
|
|
|
// foreach (string fileName in foundTempFiles)
|
|
// if (!registeredFiles.Contains(fileName, StringComparer.InvariantCultureIgnoreCase))
|
|
// try
|
|
// {
|
|
// if (File.Exists(fileName))
|
|
// File.Delete(fileName);
|
|
// }
|
|
// catch
|
|
// {
|
|
// }
|
|
//}
|
|
|
|
#endregion
|
|
#region Queue
|
|
|
|
protected List<string> queuedFiles = new List<string>();
|
|
|
|
public void QueuePermanentFilesToDelete(IEnumerable<Guid> holderIds)
|
|
{
|
|
queuedFiles = new List<string>();
|
|
var attachs = DbContext.Attachments.Where(x => holderIds.Contains(x.ParentId)).ToList();
|
|
|
|
foreach (Attachment item in attachs)
|
|
queuedFiles.Add(item.FileName);
|
|
}
|
|
|
|
public void DeleteQueuedFiles(bool silent = false)
|
|
{
|
|
if ((queuedFiles == null) || (queuedFiles.Count < 1))
|
|
return;
|
|
|
|
foreach (string fileName in queuedFiles)
|
|
try
|
|
{
|
|
if (File.Exists(fileName))
|
|
File.Delete(fileName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (!silent)
|
|
throw ex;
|
|
}
|
|
|
|
queuedFiles.Clear();
|
|
}
|
|
|
|
#endregion
|
|
#region Other public
|
|
|
|
public FileDescriptor GetFileContent(Guid fileId)
|
|
{
|
|
if (fileId.Equals(Guid.Empty))
|
|
throw new ArgumentNullException("Can't locate file for empty identifier");
|
|
|
|
if (this.IsPermanentFile(fileId))
|
|
return this.GetPermanentFileContent(fileId);
|
|
|
|
if (this.IsTempFile(fileId))
|
|
return this.GetTempFileContent(fileId);
|
|
|
|
throw new FileNotFoundException(String.Format("File (Id = {0}) not found", fileId));
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |