public Task BindModelAsync(ModelBindingContext bindingContext) { ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); string stringValue = value.FirstValue; if (String.IsNullOrEmpty(stringValue)) { bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Empty file identifier"); } else { try { FileIdentifier id = FileIdentifier.FromString(stringValue); bindingContext.Model = id; bindingContext.Result = ModelBindingResult.Success(id); } catch (ArgumentException ex) { bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex.Message); } } return(Task.CompletedTask); }
public void FileStore_GetDataFile_ReadsCorrectFile() { // Given IFileProvider fileProvider = Substitute.For <IFileProvider>(); IFileStore store = new FileStore(new FakeFileStoreFileProviderFactory(fileProvider)); // When store.GetDataFile(FileIdentifier.FromString("aaaa")); // Then fileProvider.Received(1).GetFileInfo("aaaa.dat"); }
public async Task ExecuteAsync(HttpContext context) { FileIdentifier identifier = FileIdentifier.FromString(context.GetRouteValue("fileIdentifier").ToString()); this._logger.LogInformation(LogEvents.NewUpload, "New upload of file with id {0}", identifier); // We have already the ID, so we can set some progress UploadProgress progress = new UploadProgress { Current = 0, StartTime = DateTime.UtcNow, Total = context.Request.ContentLength ?? -1 }; this._uploadProgressManager.SetProgress(identifier, progress); // Initialize reading request MediaTypeHeaderValue contentType = GetContentType(context); string boundary = GetBoundary(contentType); MultipartReader reader = new MultipartReader(boundary, context.Request.Body); reader.BodyLengthLimit = (long?)this._fileStoreOptions.Value?.MaximumFileSize.Megabytes().Bytes; // Delegate actual request parsing // ... after the request "completes" we re-execute to send the final response to the browser try { using (context.RequestAborted.Register(context.Abort)) { await this._uploadManager.StoreAsync(identifier, reader, context.RequestAborted); } PrepForReExecute(context, new UploadErrorsModel()); } catch (Exception ex) { UploadErrorsModel errors = new UploadErrorsModel { Errors = new[] { ex.Message } }; this._logger.LogError(LogEvents.UploadFailed, "Detected failed upload - passing error to child handler: {0}", ex); PrepForReExecute(context, errors); } await ReExecuteAsync(context); }
public async Task <IList <UploadedFile> > GetFiles() { var fileIds = from fileInfo in this._fileStore.GetFiles() let plainName = Path.GetFileNameWithoutExtension(fileInfo.Name) where plainName != null && FileIdentifier.IsValid(plainName) select FileIdentifier.FromString(plainName); List <UploadedFile> uploadedFiles = new List <UploadedFile>(); foreach (FileIdentifier id in fileIds.Distinct()) { UploadedFile file = await this.GetFileInternal(id).ConfigureAwait(false); if (file != null) { uploadedFiles.Add(file); } } return(uploadedFiles); }
public async Task ExpiredFileRemovalJob_RemovesObsoleteFiles() { // Given List <UploadedFile> files = new List <UploadedFile>(); var job = GetTestObject(files); files.Add(new UploadedFile(FileIdentifier.FromString("a"), new FakeFile(), new StoredMetadata { Expiration = DateTime.UtcNow.AddDays(1) })); files.Add(new UploadedFile(FileIdentifier.FromString("b"), new FakeFile(), new StoredMetadata { Expiration = DateTime.UtcNow.AddDays(-1) })); files.Add(new UploadedFile(FileIdentifier.FromString("c"), new FakeFile(), new StoredMetadata { Expiration = DateTime.UtcNow.AddMilliseconds(-1) })); // When await job.Execute(new JobCancellationToken(false)); // Then Assert.That(files, ContainsFileIdentifier(FileIdentifier.FromString("a"))); Assert.That(files, Has.Count.EqualTo(1)); }
private async Task ProcessFormSectionAsync(FileIdentifier id, MultipartSection section, StoredMetadataFactory metadataFactory, ContentDispositionHeaderValue contentDisposition) { string cleanName = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value; async Task <string> ReadString() { using (StreamReader sr = new StreamReader(section.Body)) { return(await sr.ReadToEndAsync()); } } switch (cleanName) { case nameof(UploadModel.IsReservation): string isReservationRaw = await ReadString(); metadataFactory.SetIsReservation(Boolean.Parse(isReservationRaw)); break; case nameof(UploadModel.Expiration): string dateTimeRaw = await ReadString(); // MVC we send date as roundtrip metadataFactory.SetExpiration(DateTime.ParseExact(dateTimeRaw, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind)); return; case nameof(UploadModel.FileIdentifier): string rawId = await ReadString(); FileIdentifier formId = FileIdentifier.FromString(rawId); if (formId != id) { throw new InvalidOperationException($"ID mismatch: '{formId}' (received) != '{id}' (expected)"); } return; case nameof(UploadModel.Sender) + "." + nameof(ContactInformation.Name): string name = await ReadString(); metadataFactory.SetSenderName(name); return; case nameof(UploadModel.Sender) + "." + nameof(ContactInformation.EmailAddress): string emailAddress = await ReadString(); metadataFactory.SetSenderEmail(emailAddress); return; // Browsers don't actually send the file size in the request, but we can derive it from the Content-Length. // However, that is not very accurate and if we use some javascript to send a more accurate file size, we use that. case nameof(UploadModel.SuggestedFileSize): long size; if (Int64.TryParse(await ReadString(), out size) && size > 0) { this.GetProgressObject(id).Total = size; } return; default: this._logger.LogWarning(LogEvents.UploadIncomplete, "{0}: Unknown form field '{1}'", id, contentDisposition.Name); break; } }
private async Task ProcessFormSectionAsync(UploadContext uploadContext, MultipartSection section, ContentDispositionHeaderValue contentDisposition) { string cleanName = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value; StoredMetadataFactory metadataFactory = uploadContext.MetadataFactory; UploadPassword passwordSetting = uploadContext.PasswordSetting; switch (cleanName) { case nameof(UploadModel.IsReservation): string isReservationRaw = await ReadString(); metadataFactory.SetIsReservation(Boolean.Parse(isReservationRaw)); break; case nameof(UploadModel.Expiration): string dateTimeRaw = await ReadString(); // MVC we send date as roundtrip metadataFactory.SetExpiration(DateTime.ParseExact(dateTimeRaw, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind)); return; case nameof(UploadModel.FileIdentifier): string rawId = await ReadString(); FileIdentifier formId = FileIdentifier.FromString(rawId); if (formId != uploadContext.Identifier) { throw new InvalidOperationException($"ID mismatch: '{formId}' (received) != '{uploadContext.Identifier}' (expected)"); } return; case nameof(UploadModel.Password): string password = await ReadString(); metadataFactory.SetPassword(password); passwordSetting.Password = password; EnsureFileNotUploaded(); return; case nameof(UploadModel.EnablePasswordProtection): bool passwordSettingWasSet = passwordSetting.IsSet; string enablePasswordProtectionRaw = await ReadString(); bool enablePasswordProtection = String.Equals(Boolean.TrueString, enablePasswordProtectionRaw, StringComparison.OrdinalIgnoreCase); metadataFactory.SetEnablePasswordProtection(enablePasswordProtection); passwordSetting.SetEnabled(enablePasswordProtection); if (!passwordSettingWasSet) { EnsureFileNotUploaded(); } return; case nameof(UploadModel.Sender) + "." + nameof(ContactInformation.Name): string name = await ReadString(); metadataFactory.SetSenderName(name); return; case nameof(UploadModel.Sender) + "." + nameof(ContactInformation.EmailAddress): string emailAddress = await ReadString(); metadataFactory.SetSenderEmail(emailAddress); return; // Browsers don't actually send the file size in the request, but we can derive it from the Content-Length. // However, that is not very accurate and if we use some javascript to send a more accurate file size, we use that. case nameof(UploadModel.SuggestedFileSize): if (Int64.TryParse(await ReadString(), out var size) && size > 0) { this.GetProgressObject(uploadContext.Identifier).Total = size; } return; default: this._logger.LogWarning(LogEvents.UploadIncomplete, "{Identifier}: Unknown form field '{Field}'", uploadContext.Identifier, contentDisposition.Name); break; } async Task <string> ReadString() { using (StreamReader sr = new StreamReader(section.Body)) { return(await sr.ReadToEndAsync()); } } void EnsureFileNotUploaded() { bool needToValidate = !String.IsNullOrEmpty(passwordSetting.Password) && passwordSetting.Enable == true; if (needToValidate && uploadContext.HasUploadedFile) { this._logger.LogError(LogEvents.UploadPasswordAfterFileUpload, "{Identifier}: The upload password is set after the file is uploaded. The file is not encrypted. Terminating upload.", uploadContext.Identifier); throw new UploadCryptoArgumentOrderException("File uploaded before password has been set"); } } }