/// <summary> /// Creates an action result with a thumbnail image of a file in the storage. /// </summary> /// <param name="originalMetadata">Metadata of the original image file.</param> /// <param name="storage">The storage service used to store files.</param> /// <param name="dateTimeService">Date time service used to get current date and time.</param> /// <param name="maxWidth">Maximum width of the thumbnail image.</param> /// <param name="maxHeight">Maximum height of the thumbnail image.</param> /// <param name="useCache">Whether to use a cached thumbnail or not.</param> /// <returns>The ActionResult containing the thumbnail image.</returns> protected ActionResult GetOrCreateThumb( FileMetadata originalMetadata, IBlobStorageManager storage, IDateTimeService dateTimeService, int maxWidth, int maxHeight, bool useCache = true) { if (originalMetadata == null) { throw new ArgumentNullException("originalMetadata"); } if (originalMetadata.OwnerUserId == this.DbUser.Id) { var fileNamePrefix = Path.GetDirectoryName(originalMetadata.BlobName) + "\\"; var normalFileName = StringHelper.NormalizeFileName(originalMetadata.SourceFileName); var thumbName = string.Format( "{0}\\{1}file-{2}-thumb-{4}x{5}-{3}", originalMetadata.ContainerName, fileNamePrefix, originalMetadata.Id, normalFileName, maxWidth, maxHeight); var fileName = string.Format("{0}\\{1}", originalMetadata.ContainerName, originalMetadata.BlobName); int originalMetadataId = originalMetadata.Id; var metadataProvider = new DbFileMetadataProvider(this.db, dateTimeService, this.DbUser.PracticeId); var thumbResult = ImageHelper.TryGetOrCreateThumb( originalMetadataId, maxWidth, maxHeight, fileName, thumbName, useCache, storage, metadataProvider); switch (thumbResult.Status) { case CreateThumbStatus.Ok: return(this.File(thumbResult.Data, thumbResult.ContentType)); case CreateThumbStatus.SourceFileNotFound: return(new StatusCodeResult(HttpStatusCode.NotFound)); case CreateThumbStatus.SourceIsNotImage: return(this.Redirect(this.Url.Content("~/Content/Images/App/FileIcons/generic-outline.png"))); case CreateThumbStatus.SourceImageTooLarge: return(this.Redirect(this.Url.Content("~/Content/Images/App/FileIcons/generic-outline.png"))); default: throw new NotImplementedException(); } } return(new StatusCodeResult(HttpStatusCode.NotFound)); }
public FilesStatus GetFilesStatus(PatientFileViewModel fileModel, string prefix) { var fileName = fileModel.SourceFileName; var containerName = fileModel.ContainerName; var sourceFileName = Path.GetFileName(fileModel.SourceFileName ?? "") ?? ""; var normalFileName = StringHelper.RemoveDiacritics(sourceFileName.ToLowerInvariant()); var fileNamePrefix = Path.GetDirectoryName(fileModel.BlobName) + "\\"; var fullStoragePath = string.Format("{0}\\{1}file-{2}-{3}", containerName, fileNamePrefix, fileModel.Id, normalFileName); var fileStatus = new FilesStatus(fileModel.Id, fileModel.MetadataId, fileName, fileModel.FileLength, prefix, fileModel.FileTitle); var isPatientFiles = Regex.IsMatch(fileModel.ContainerName, @"^patient-files-\d+$"); // Validating each file location... otherwise this could be a security hole. if (!isPatientFiles) throw new Exception("Invalid file location for patient files."); var fileMetadataProvider = new DbFileMetadataProvider(this.db, this.datetimeService, this.DbUser.PracticeId); bool imageThumbOk = false; try { var thumbName = string.Format("{0}\\{1}file-{2}-thumb-{4}x{5}-{3}", containerName, fileNamePrefix, fileModel.MetadataId, normalFileName, 120, 120); var thumbResult = ImageHelper.TryGetOrCreateThumb(fileModel.MetadataId, 120, 120, fullStoragePath, thumbName, true, storage, fileMetadataProvider); if (thumbResult.Status == CreateThumbStatus.Ok) { fileStatus.ThumbnailUrl = @"data:" + thumbResult.ContentType + ";base64," + Convert.ToBase64String(thumbResult.Data); fileStatus.IsInGallery = true; imageThumbOk = true; } } // ReSharper disable EmptyGeneralCatchClause catch // ReSharper restore EmptyGeneralCatchClause { } if (!imageThumbOk) { if (StringHelper.IsDocumentFileName(fileName)) { fileStatus.IconClass = "document-file-icon"; } else { fileStatus.IconClass = "generic-file-icon"; } } bool isTemp = fileModel.Id == null; if (isTemp) { var location = string.Format("{0}\\{1}", fileModel.ContainerName, fileModel.BlobName); if (imageThumbOk) fileStatus.UrlLarge = this.Url.Action("Image", "TempFile", new { w = 1024, h = 768, id = fileModel.MetadataId, location }); fileStatus.UrlFull = this.Url.Action("File", "TempFile", new { id = fileModel.MetadataId, location }); } else { if (imageThumbOk) fileStatus.UrlLarge = this.Url.Action("Image", "PatientFiles", new { w = 1024, h = 768, id = fileModel.Id }); fileStatus.UrlFull = this.Url.Action("File", "PatientFiles", new { id = fileModel.Id }); } return fileStatus; }
public ActionResult Edit(Dictionary<string, PatientFilesGroupViewModel> patientFilesGroups) { var kv = patientFilesGroups.Single(); var formModel = kv.Value; PatientFileGroup dbFileGroup; if (formModel.Id == null) { Debug.Assert(formModel.PatientId != null, "formModel.PatientId != null"); dbFileGroup = new PatientFileGroup { PatientId = formModel.PatientId.Value, PracticeId = this.DbUser.PracticeId, CreatedOn = this.datetimeService.UtcNow, }; this.db.PatientFileGroups.AddObject(dbFileGroup); } else { dbFileGroup = this.db.PatientFileGroups .Include("PatientFiles") .Include("PatientFiles.FileMetadata") .FirstOrDefault(pe => pe.Id == formModel.Id); } Debug.Assert(dbFileGroup != null, "dbFileGroup != null"); var allExistingFilesInGroup = dbFileGroup.PatientFiles.ToDictionary(pf => pf.Id); var idsToKeep = new HashSet<int>(formModel.Files.Where(f => f.Id != null).Select(f => f.Id.Value)); var storageActions = new List<Action>(formModel.Files.Count); var metadataProvider = new DbFileMetadataProvider(this.db, this.datetimeService, this.DbUser.PracticeId); var metadataDic = metadataProvider.GetByIds(formModel.Files.Select(f => f.MetadataId).ToArray()).ToDictionary(f => f.Id); foreach (var eachFile in formModel.Files) { // Validating each file location... otherwise this could be a security hole. FileMetadata metadata; metadataDic.TryGetValue(eachFile.MetadataId, out metadata); if (metadata == null) return new StatusCodeResult(HttpStatusCode.NotFound, "Arquivo não encontrado. Outra pessoa deve ter removido esse arquivo neste instante."); var validContainer = string.Format("patient-files-{0}", this.DbUser.Id); if (metadata.ContainerName != validContainer) throw new Exception("Invalid file location."); PatientFile patientFile; if (eachFile.Id == null) { // creating and adding the new patient file Debug.Assert(formModel.PatientId != null, "formModel.PatientId != null"); patientFile = new PatientFile { FileMetadataId = metadata.Id, PatientId = formModel.PatientId.Value, PracticeId = this.DbUser.PracticeId, }; dbFileGroup.PatientFiles.Add(patientFile); // changing file metadata: // - it is not temporary anymore // - tag is free for another operation metadata.ExpirationDate = null; metadata.Tag = null; } else if (!allExistingFilesInGroup.TryGetValue(eachFile.Id.Value, out patientFile)) { return new StatusCodeResult(HttpStatusCode.NotFound, "Arquivo não encontrado. Outra pessoa deve ter removido esse arquivo neste instante."); } Debug.Assert(patientFile != null, "patientFile != null"); patientFile.Title = eachFile.FileTitle; } // deleting files that were removed foreach (var patientFileKv in allExistingFilesInGroup) { if (!idsToKeep.Contains(patientFileKv.Key)) { // create delegate to kill the file metadata and the storage blob // this is going to be called latter var metadata = patientFileKv.Value.FileMetadata; Action removeFile = () => TempFileController.DeleteFileByMetadata(metadata, this.db, this.storage); storageActions.Add(removeFile); // delete patient file (note that changes are not being saved yet) this.db.PatientFiles.DeleteObject(patientFileKv.Value); } } if (formModel.Files.Count == 0) { this.ModelState.AddModelError(string.Format("PatientFilesGroups[{0}].Files", kv.Key), "Deve haver pelo menos um arquivo na lista."); } if (this.ModelState.IsValid) { dbFileGroup.GroupTitle = formModel.Title; dbFileGroup.GroupNotes = formModel.Notes; Debug.Assert(formModel.FileGroupDate != null, "formModel.FileGroupDate != null"); dbFileGroup.FileGroupDate = this.ConvertToUtcDateTime(formModel.FileGroupDate.Value); Debug.Assert(formModel.ReceiveDate != null, "formModel.ReceiveDate != null"); dbFileGroup.ReceiveDate = this.ConvertToUtcDateTime(formModel.ReceiveDate.Value); dbFileGroup.Patient.IsBackedUp = false; this.db.SaveChanges(); // moving files that are stored in a temporary location foreach (var moveAction in storageActions) moveAction(); return this.View("Details", GetViewModel(this.storage, dbFileGroup, this.DbUser.Id, this.GetToLocalDateTimeConverter())); } FillMissingInfos(formModel, this.db.FileMetadatas); FillFileLengths(this.storage, formModel, this.DbUser.Id); this.ViewBag.FilesStatusGetter = (FilesStatusGetter)this.GetFilesStatus; return this.View("Edit", formModel); }
/// <summary> /// Creates an action result with a thumbnail image of a file in the storage. /// </summary> /// <param name="originalMetadata">Metadata of the original image file.</param> /// <param name="storage">The storage service used to store files.</param> /// <param name="dateTimeService">Date time service used to get current date and time.</param> /// <param name="maxWidth">Maximum width of the thumbnail image.</param> /// <param name="maxHeight">Maximum height of the thumbnail image.</param> /// <param name="useCache">Whether to use a cached thumbnail or not.</param> /// <returns>The ActionResult containing the thumbnail image.</returns> protected ActionResult GetOrCreateThumb( FileMetadata originalMetadata, IBlobStorageManager storage, IDateTimeService dateTimeService, int maxWidth, int maxHeight, bool useCache = true) { if (originalMetadata == null) throw new ArgumentNullException("originalMetadata"); if (originalMetadata.OwnerUserId == this.DbUser.Id) { var fileNamePrefix = Path.GetDirectoryName(originalMetadata.BlobName) + "\\"; var normalFileName = StringHelper.NormalizeFileName(originalMetadata.SourceFileName); var thumbName = string.Format( "{0}\\{1}file-{2}-thumb-{4}x{5}-{3}", originalMetadata.ContainerName, fileNamePrefix, originalMetadata.Id, normalFileName, maxWidth, maxHeight); var fileName = string.Format("{0}\\{1}", originalMetadata.ContainerName, originalMetadata.BlobName); int originalMetadataId = originalMetadata.Id; var metadataProvider = new DbFileMetadataProvider(this.db, dateTimeService, this.DbUser.PracticeId); var thumbResult = ImageHelper.TryGetOrCreateThumb( originalMetadataId, maxWidth, maxHeight, fileName, thumbName, useCache, storage, metadataProvider); switch (thumbResult.Status) { case CreateThumbStatus.Ok: return this.File(thumbResult.Data, thumbResult.ContentType); case CreateThumbStatus.SourceFileNotFound: return new StatusCodeResult(HttpStatusCode.NotFound); case CreateThumbStatus.SourceIsNotImage: return this.Redirect(this.Url.Content("~/Content/Images/App/FileIcons/generic-outline.png")); case CreateThumbStatus.SourceImageTooLarge: return this.Redirect(this.Url.Content("~/Content/Images/App/FileIcons/generic-outline.png")); default: throw new NotImplementedException(); } } return new StatusCodeResult(HttpStatusCode.NotFound); }
/// <summary> /// Upload whole file. /// </summary> /// <param name="prefix"> The prefix of the fields to be placed in the HTML. </param> /// <param name="location"> The location where the temporary file should be stored. </param> /// <returns> The <see cref="ActionResult"/> containing information about execution of the upload. </returns> private ActionResult UploadWholeFile(string prefix, string location, string tag) { var statuses = new List<FilesStatus>(); for (int i = 0; i < this.Request.Files.Count; i++) { var file = this.Request.Files[i]; Debug.Assert(file != null, "file != null"); var containerName = location.Split("\\".ToCharArray(), 2).FirstOrDefault(); var sourceFileName = Path.GetFileName(file.FileName ?? "") ?? ""; var normalFileName = StringHelper.NormalizeFileName(sourceFileName); var fileNamePrefix = location.Split("\\".ToCharArray(), 2).Skip(1).FirstOrDefault(); var fileExpirationDate = this.datetimeService.UtcNow + TimeSpan.FromDays(file.ContentLength < 10 * 1024000 ? 2 : 10); Debug.Assert(sourceFileName != null, "sourceFileName != null"); var metadataProvider = new DbFileMetadataProvider(this.db, this.datetimeService, this.DbUser.PracticeId); // creating the metadata entry for the main file FileMetadata metadata = metadataProvider.CreateTemporary( containerName, sourceFileName, string.Format("{0}file-{1}-{2}", fileNamePrefix, "{id}", normalFileName), fileExpirationDate, this.DbUser.Id, tag, formatWithId: true); metadata.OwnerUserId = this.DbUser.Id; metadataProvider.SaveChanges(); // saving the file to the storage this.storage.UploadFileToStorage(file.InputStream, containerName, metadata.BlobName); // returning information to the client var fileStatus = new FilesStatus(metadata.Id, sourceFileName, file.ContentLength, prefix); bool imageThumbOk = false; try { var fullStoragePath = string.Format("{0}\\{1}", containerName, metadata.BlobName); var thumbName = string.Format("{0}\\{1}file-{2}-thumb-{4}x{5}-{3}", containerName, fileNamePrefix, metadata.Id, normalFileName, 120, 120); var thumbResult = ImageHelper.TryGetOrCreateThumb(metadata.Id, 120, 120, fullStoragePath, thumbName, true, this.storage, metadataProvider); if (thumbResult.Status == CreateThumbStatus.Ok) { fileStatus.ThumbnailUrl = @"data:" + thumbResult.ContentType + ";base64," + Convert.ToBase64String(thumbResult.Data); fileStatus.IsInGallery = true; imageThumbOk = true; } } // ReSharper disable EmptyGeneralCatchClause catch // ReSharper restore EmptyGeneralCatchClause { } if (!imageThumbOk) { if (StringHelper.IsDocumentFileName(sourceFileName)) { fileStatus.IconClass = "document-file-icon"; } else { fileStatus.IconClass = "generic-file-icon"; } } else { fileStatus.UrlLarge = this.Url.Action("Image", new { w = 1024, h = 768, location, metadata.Id }); } fileStatus.UrlFull = this.Url.Action("File", new { location, metadata.Id }); fileStatus.DeleteUrl = this.Url.Action("Index", new { location, metadata.Id }); statuses.Add(fileStatus); } return this.JsonIframeSafe(new { files = statuses }); }