public async Task <StoredFileDto> GetEntityPropertyAsync([FromQuery] StoredFileAsPropertyDto input) { if (string.IsNullOrWhiteSpace(input.OwnerType) || string.IsNullOrWhiteSpace(input.OwnerId) || string.IsNullOrWhiteSpace(input.PropertyName)) { return(null); } var owner = await _dynamicRepository.GetAsync(input.OwnerType, input.OwnerId); if (owner == null) { return(null); } var property = ReflectionHelper.GetProperty(owner, input.PropertyName); if (property == null) { throw new Exception($"Property '{input.PropertyName}' not found in the class {owner.GetType().Name}"); } if (!(property.GetValue(owner) is StoredFile storedFile && !storedFile.IsDeleted)) { return(null); } return(GetFileDto(storedFile)); }
public async Task <StoredFileDto> UploadAsync([FromForm] UploadFileInput input) { if (string.IsNullOrWhiteSpace(input.OwnerType)) { ModelState.AddModelError(nameof(input.OwnerType), $"{nameof(input.OwnerType)} must not be null"); } if (string.IsNullOrWhiteSpace(input.OwnerId)) { ModelState.AddModelError(nameof(input.OwnerId), $"{nameof(input.OwnerId)} must not be null"); } if (input.File == null) { ModelState.AddModelError(nameof(input.File), $"{nameof(input.File)} must not be null"); } if (!ModelState.IsValid) { throw new AbpValidationException("An error occured");//, ModelState.Keys.Select(k => new ValidationResult(ModelState.Values[k], new List<string>() { k }))); } var owner = await _dynamicRepository.GetAsync(input.OwnerType, input.OwnerId); if (owner == null) { throw new Exception($"Owner not found (type = '{input.OwnerType}', id = '{input.OwnerId}')"); } var uploadedFile = new StoredFileDto(); var fileName = input.File.FileName.CleanupFileName(); if (!string.IsNullOrWhiteSpace(input.PropertyName)) { // single file upload (stored as a property of an entity) var property = ReflectionHelper.GetProperty(owner, input.PropertyName); if (property == null || property.PropertyType != typeof(StoredFile)) { throw new Exception( $"Property '{input.PropertyName}' not found in class '{owner.GetType().FullName}'"); } if (property.GetValue(owner, null) is StoredFile storedFile) { storedFile.IsVersionControlled = true; var version = await _fileService.GetNewOrDefaultVersionAsync(storedFile); version.FileName = fileName; version.FileType = Path.GetExtension(fileName); await _fileVersionRepository.InsertOrUpdateAsync(version); await using (var fileStream = input.File.OpenReadStream()) { await _fileService.UpdateVersionContentAsync(version, fileStream); } // copy to the main todo: remove duplicated properties (filename, filetype), add a link to the last version and update it using triggers storedFile.FileName = version.FileName; storedFile.FileType = version.FileType; await _fileRepository.UpdateAsync(storedFile); } else { await using (var fileStream = input.File.OpenReadStream()) { storedFile = await _fileService.SaveFile(fileStream, fileName); property.SetValue(owner, storedFile, null); } } await _unitOfWorkManager.Current.SaveChangesAsync(); MapStoredFile(storedFile, uploadedFile); } else { // add file as an attachment (linked to an entity using OwnerType and OwnerId) await using (var fileStream = input.File.OpenReadStream()) { var storedFile = await _fileService.SaveFile(fileStream, fileName, file => { file.SetOwner(input.OwnerType, input.OwnerId); file.Category = input.FilesCategory; }); await _unitOfWorkManager.Current.SaveChangesAsync(); MapStoredFile(storedFile, uploadedFile); } } /* * 1. property of entity (ownerid+type+property) * 2. attachments list (ownerid+type+category) * 3. direct upload using id (id) */ return(uploadedFile); }
public async Task <StoredFileDto> CreateOrUpdateAsync([FromForm] CreateStoredFileInput input) { if (input.File == null) { ModelState.AddModelError(nameof(input.File), $"{nameof(input.File)} must not be null"); } var ownerSpecified = !string.IsNullOrWhiteSpace(input.OwnerType) && !string.IsNullOrWhiteSpace(input.OwnerId); if (string.IsNullOrWhiteSpace(input.OwnerId) && !string.IsNullOrWhiteSpace(input.OwnerType)) { ModelState.AddModelError(nameof(input.OwnerId), $"{nameof(input.OwnerId)} must not be null when {nameof(input.OwnerType)} is specified"); } if (string.IsNullOrWhiteSpace(input.OwnerType) && !string.IsNullOrWhiteSpace(input.OwnerId)) { ModelState.AddModelError(nameof(input.OwnerType), $"{nameof(input.OwnerType)} must not be null when {nameof(input.OwnerId)} is specified"); } if (input.Id == null && string.IsNullOrWhiteSpace(input.PropertyName)) { ModelState.AddModelError(nameof(input.Id), $"Id must not be null"); } var owner = ownerSpecified ? await _dynamicRepository.GetAsync(input.OwnerType, input.OwnerId) : null; if (ownerSpecified && owner == null) { ModelState.AddModelError(input.OwnerId, $"Owner not found (type = '{input.OwnerType}', id = '{input.OwnerId}')"); } var uploadAsProperty = owner != null && !string.IsNullOrWhiteSpace(input.PropertyName); var property = uploadAsProperty ? ReflectionHelper.GetProperty(owner, input.PropertyName) : null; if (uploadAsProperty) { if (property == null) { ModelState.AddModelError(nameof(input.PropertyName), $"Property '{owner.GetType().Name}.{input.PropertyName}' not found"); } if (property != null && !typeof(StoredFile).IsAssignableFrom(property.PropertyType)) { ModelState.AddModelError(nameof(input.PropertyName), $"Wrong type of '{owner.GetType().Name}.{input.PropertyName}' property (actual: '{property.PropertyType.FullName}', expected: '{nameof(StoredFile)}')"); } } if (!ModelState.IsValid) { throw new AbpValidationException("Failed to upload file", GetValidationResults(ModelState)); } StoredFile storedFile; // allow to use predefined Id and re-activate existing storedfile using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete)) { storedFile = input.Id != null ? await _fileRepository.GetAll().FirstOrDefaultAsync(f => f.Id == input.Id.Value) : property != null ? property.GetValue(owner) as StoredFile : null; } var fileName = input.File.FileName.CleanupFileName(); if (storedFile == null) { await using (var fileStream = input.File.OpenReadStream()) { storedFile = await _fileService.SaveFile(fileStream, fileName, file => { // set predefined Id if (input.Id.HasValue && input.Id.Value != Guid.Empty) { file.Id = input.Id.Value; } }); // set property if needed if (property != null) { property.SetValue(owner, storedFile, null); await _dynamicRepository.SaveOrUpdateAsync(owner); } } } else { storedFile.IsDeleted = false; storedFile.IsVersionControlled = true; var version = await _fileService.GetNewOrDefaultVersionAsync(storedFile); version.FileName = fileName; version.FileType = Path.GetExtension(fileName); await _fileVersionRepository.InsertOrUpdateAsync(version); await using (var fileStream = input.File.OpenReadStream()) { await _fileService.UpdateVersionContentAsync(version, fileStream); } // copy to the main todo: remove duplicated properties (filename, filetype), add a link to the last version and update it using triggers storedFile.FileName = version.FileName; storedFile.FileType = version.FileType; await _fileRepository.UpdateAsync(storedFile); } var uploadedFile = new StoredFileDto(); await _unitOfWorkManager.Current.SaveChangesAsync(); MapStoredFile(storedFile, uploadedFile); return(uploadedFile); }
public async Task <bool> Delete([FromQuery] DeleteStoredFileInput input) { var ownerSpecified = !string.IsNullOrWhiteSpace(input.OwnerType) && !string.IsNullOrWhiteSpace(input.OwnerId); if (string.IsNullOrWhiteSpace(input.OwnerId) && !string.IsNullOrWhiteSpace(input.OwnerType)) { ModelState.AddModelError(nameof(input.OwnerId), $"{nameof(input.OwnerId)} must not be null when {nameof(input.OwnerType)} is specified"); } if (string.IsNullOrWhiteSpace(input.OwnerType) && !string.IsNullOrWhiteSpace(input.OwnerId)) { ModelState.AddModelError(nameof(input.OwnerType), $"{nameof(input.OwnerType)} must not be null when {nameof(input.OwnerId)} is specified"); } if (input.FileId == null && string.IsNullOrWhiteSpace(input.PropertyName)) { ModelState.AddModelError(nameof(input.FileId), $"Id must not be null"); } var owner = ownerSpecified ? await _dynamicRepository.GetAsync(input.OwnerType, input.OwnerId) : null; if (ownerSpecified && owner == null) { ModelState.AddModelError(input.OwnerId, $"Owner not found (type = '{input.OwnerType}', id = '{input.OwnerId}')"); } var processAsProperty = owner != null && !string.IsNullOrWhiteSpace(input.PropertyName); var property = processAsProperty ? ReflectionHelper.GetProperty(owner, input.PropertyName) : null; if (processAsProperty) { if (property == null) { ModelState.AddModelError(nameof(input.PropertyName), $"Property '{owner.GetType().Name}.{input.PropertyName}' not found"); } if (property != null && !typeof(StoredFile).IsAssignableFrom(property.PropertyType)) { ModelState.AddModelError(nameof(input.PropertyName), $"Wrong type of '{owner.GetType().Name}.{input.PropertyName}' property (actual: '{property.PropertyType.FullName}', expected: '{nameof(StoredFile)}')"); } } if (!ModelState.IsValid) { throw new AbpValidationException("Failed to delete file", GetValidationResults(ModelState)); } var storedFile = input.FileId != null ? await _fileRepository.GetAll().FirstOrDefaultAsync(f => f.Id == input.FileId.Value) : property != null ? property.GetValue(owner) as StoredFile : null; if (storedFile != null) { // if the `property` is specified - then it's direct link and we should set it to null if (property != null) { property.SetValue(owner, null, null); await _dynamicRepository.SaveOrUpdateAsync(owner); } await _fileService.DeleteAsync(storedFile); } return(true); }