public async Task CreateFileAsync_Throws_An_Exception_If_The_File_Id_Already_Exist() { var expectedFileId = Guid.NewGuid().ToString(); var nonUniqueFileIdProvider = Substitute.For <ITusFileIdProvider>(); nonUniqueFileIdProvider.CreateId(null).ReturnsForAnyArgs(expectedFileId); nonUniqueFileIdProvider.ValidateId(null).ReturnsForAnyArgs(true); var store = new TusDiskStore(_fixture.Path, false, TusDiskBufferSize.Default, nonUniqueFileIdProvider); var fileId = await store.CreateFileAsync(1, null, CancellationToken.None); fileId.ShouldBe(expectedFileId); await store.AppendDataAsync(fileId, new MemoryStream(new[] { (byte)1 }), CancellationToken.None); var filePath = Path.Combine(_fixture.Path, fileId); File.Exists(filePath).ShouldBeTrue(); new FileInfo(filePath).Length.ShouldBe(1); await Assert.ThrowsAnyAsync <Exception>(async() => await store.CreateFileAsync(1, null, CancellationToken.None)); File.Exists(filePath).ShouldBeTrue(); new FileInfo(filePath).Length.ShouldBe(1); }
public async Task AppendDataAsync_Uses_The_Read_And_Write_Buffers_Correctly(int readBufferSize, int writeBufferSize, int fileSize, int expectedNumberOfWrites, int expectedNumberOfReads) { int readsPerWrite = (int)Math.Ceiling((double)writeBufferSize / readBufferSize); var store = new TusDiskStore(_fixture.Path, false, new TusDiskBufferSize(writeBufferSize, readBufferSize)); var totalNumberOfWrites = 0; var totalNumberOfReads = 0; var numberOfReadsSinceLastWrite = 0; var firstWrite = true; int bytesWritten = 0; var fileId = await store.CreateFileAsync(fileSize, null, CancellationToken.None); var requestStream = new RequestStreamFake(async(RequestStreamFake stream, byte[] bufferToFill, int offset, int count, CancellationToken cancellationToken) => { count.ShouldBe(readBufferSize); numberOfReadsSinceLastWrite++; var bytesRead = await stream.ReadBackingStreamAsync(bufferToFill, offset, count, cancellationToken); // Need to subtract from readsPerWrite due to this expression being checked _after_ the write has happened. var previousReadShouldHaveTriggeredWrite = numberOfReadsSinceLastWrite == readsPerWrite - (firstWrite ? 0 : 1) + 1; if (bytesRead != 0 && previousReadShouldHaveTriggeredWrite) { numberOfReadsSinceLastWrite = 0; firstWrite = false; GetLengthFromFileOnDisk().ShouldBe(bytesWritten); totalNumberOfWrites++; } totalNumberOfReads++; bytesWritten += bytesRead; return(bytesRead); }, new byte[fileSize]); await store.AppendDataAsync(fileId, requestStream, CancellationToken.None); GetLengthFromFileOnDisk().ShouldBe(fileSize); totalNumberOfWrites++; // -1 due to the last read returning 0 bytes as the stream is then drained Assert.Equal(expectedNumberOfReads, totalNumberOfReads - 1); Assert.Equal(expectedNumberOfWrites, totalNumberOfWrites); long GetLengthFromFileOnDisk() { return(new FileInfo(Path.Combine(_fixture.Path, fileId)).Length); } }
public TusDiskStoreFixture() { Path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetTempFileName().Replace(".", "")); ClearPath(); Store = new TusDiskStore(Path); }
public async Task CreateFinalFileAsync_Deletes_Partial_Files_If_Configuration_Says_So() { // Use default constructor (implying cleanup = false) var store = new TusDiskStore(_fixture.Path); var p1 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); var p2 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); await store.AppendDataAsync(p1, new MemoryStream(new byte[] { 1 }), CancellationToken.None); await store.AppendDataAsync(p2, new MemoryStream(new byte[] { 2 }), CancellationToken.None); _ = await store.CreateFinalFileAsync(new[] { p1, p2 }, null, CancellationToken.None); (await store.FileExistAsync(p1, CancellationToken.None)).ShouldBeTrue(); (await store.FileExistAsync(p2, CancellationToken.None)).ShouldBeTrue(); // Cleanup = true store = new TusDiskStore(_fixture.Path, true); p1 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); p2 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); await store.AppendDataAsync(p1, new MemoryStream(new byte[] { 1 }), CancellationToken.None); await store.AppendDataAsync(p2, new MemoryStream(new byte[] { 2 }), CancellationToken.None); _ = await store.CreateFinalFileAsync(new[] { p1, p2 }, null, CancellationToken.None); (await store.FileExistAsync(p1, CancellationToken.None)).ShouldBeFalse(); (await store.FileExistAsync(p2, CancellationToken.None)).ShouldBeFalse(); // Assert that all files are gone (regression on bug) var p1Files = Directory.EnumerateFiles(_fixture.Path, p1 + "*"); p1Files.Any().ShouldBeFalse("Meta files for partial file 1 has not been deleted"); var p2Files = Directory.EnumerateFiles(_fixture.Path, p2 + "*"); p2Files.Any().ShouldBeFalse("Meta files for partial file 1 has not been deleted"); // Cleanup = false store = new TusDiskStore(_fixture.Path, false); p1 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); p2 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); await store.AppendDataAsync(p1, new MemoryStream(new byte[] { 1 }), CancellationToken.None); await store.AppendDataAsync(p2, new MemoryStream(new byte[] { 2 }), CancellationToken.None); _ = await store.CreateFinalFileAsync(new[] { p1, p2 }, null, CancellationToken.None); (await store.FileExistAsync(p1, CancellationToken.None)).ShouldBeTrue(); (await store.FileExistAsync(p2, CancellationToken.None)).ShouldBeTrue(); }
public async Task CreateFinalFileAsync_Deletes_Partial_Files_If_Configuration_Says_So() { // Use default constructor. var store = new TusDiskStore(_fixture.Path); var p1 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); var p2 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); await store.AppendDataAsync(p1, new MemoryStream(new byte[] { 1 }), CancellationToken.None); await store.AppendDataAsync(p2, new MemoryStream(new byte[] { 2 }), CancellationToken.None); var f = await store.CreateFinalFileAsync(new[] { p1, p2 }, null, CancellationToken.None); f.ShouldNotBeNullOrWhiteSpace(); (await store.FileExistAsync(p1, CancellationToken.None)).ShouldBeTrue(); (await store.FileExistAsync(p2, CancellationToken.None)).ShouldBeTrue(); // Cleanup = true store = new TusDiskStore(_fixture.Path, true); p1 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); p1.ShouldNotBeNullOrWhiteSpace(); p2 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); p2.ShouldNotBeNullOrWhiteSpace(); await store.AppendDataAsync(p1, new MemoryStream(new byte[] { 1 }), CancellationToken.None); await store.AppendDataAsync(p2, new MemoryStream(new byte[] { 2 }), CancellationToken.None); f = await store.CreateFinalFileAsync(new[] { p1, p2 }, null, CancellationToken.None); f.ShouldNotBeNullOrWhiteSpace(); (await store.FileExistAsync(p1, CancellationToken.None)).ShouldBeFalse(); (await store.FileExistAsync(p2, CancellationToken.None)).ShouldBeFalse(); // Cleanup = false store = new TusDiskStore(_fixture.Path, false); p1 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); p2 = await store.CreatePartialFileAsync(1, null, CancellationToken.None); await store.AppendDataAsync(p1, new MemoryStream(new byte[] { 1 }), CancellationToken.None); await store.AppendDataAsync(p2, new MemoryStream(new byte[] { 2 }), CancellationToken.None); f = await store.CreateFinalFileAsync(new[] { p1, p2 }, null, CancellationToken.None); f.ShouldNotBeNullOrWhiteSpace(); (await store.FileExistAsync(p1, CancellationToken.None)).ShouldBeTrue(); (await store.FileExistAsync(p2, CancellationToken.None)).ShouldBeTrue(); }
public async Task CreateFileAsync_Uses_The_Provided_TusFileIdProvider_To_Create_Ids() { var customProvider = Substitute.For <ITusFileIdProvider>(); var customFileId = 0; var createIdCalls = 0; customProvider.CreateId(null).ReturnsForAnyArgs(_ => (++customFileId).ToString()).AndDoes(_ => createIdCalls++); customProvider.ValidateId(null).ReturnsForAnyArgs(true); var store = new TusDiskStore(_fixture.Path, true, TusDiskBufferSize.Default, customProvider); for (var i = 0; i < 10; i++) { var fileId = await store.CreateFileAsync(i, null, CancellationToken.None); fileId.ShouldBe(customFileId.ToString()); var filePath = Path.Combine(_fixture.Path, fileId); File.Exists(filePath).ShouldBeTrue(); createIdCalls.ShouldBe(i + 1); } }
public void CreateNewStore() { Store = new TusDiskStore(Path); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); //app.UseCors(options => options.WithOrigins("https://*****:*****@"C:\Users\chunc\Documents\RuneLaboratory\Freelance\FileUploadService\StoredFiles\"), // On what url should we listen for uploads? UrlPath = "/tusUpload", Events = new Events { OnAuthorizeAsync = eventContext => { // if (!eventContext.HttpContext.User.Identity.IsAuthenticated) // { // System.Console.WriteLine("DEBUG XXX 2"); // eventContext.FailRequest(HttpStatusCode.Unauthorized); // return Task.CompletedTask; // } // Do other verification on the user; claims, roles, etc. In this case, check the username. // if (eventContext.HttpContext.User.Identity.Name != "test") // { // System.Console.WriteLine("DEBUG XXX 3 Identity name = " + eventContext.HttpContext.User.Identity.Name); // eventContext.FailRequest(HttpStatusCode.Forbidden, "'test' is the only allowed user"); // return Task.CompletedTask; // } // Verify different things depending on the intent of the request. // E.g.: // Does the file about to be written belong to this user? // Is the current user allowed to create new files or have they reached their quota? // etc etc switch (eventContext.Intent) { case IntentType.CreateFile: System.Console.WriteLine("This is Create File API"); break; case IntentType.ConcatenateFiles: System.Console.WriteLine("This is Concatenate Files API"); break; case IntentType.WriteFile: System.Console.WriteLine("This is Write Files API"); break; case IntentType.DeleteFile: System.Console.WriteLine("This is Delete File API"); break; case IntentType.GetFileInfo: System.Console.WriteLine("This is Get File Info API"); break; case IntentType.GetOptions: System.Console.WriteLine("This is Get Options Files API"); break; default: break; } return(Task.CompletedTask); }, OnFileCompleteAsync = async eventContext => { // eventContext.FileId is the id of the file that was uploaded. // eventContext.Store is the data store that was used (in this case an instance of the TusDiskStore) // A normal use case here would be to read the file and do some processing on it. ITusFile file = await eventContext.GetFileAsync(); var result = await DoSomeProcessing(file, eventContext.CancellationToken); System.Console.WriteLine("Tus File upload complete YEah l " + file.Id); async Task <string> DoSomeProcessing(ITusFile file, CancellationToken eventContext) { System.Console.WriteLine(); System.Console.WriteLine("Tus File upload complete YEah :" + file.Id); return("success"); } if (result != "success") { //throw new MyProcessingException("Something went wrong during processing"); } } } });
public async Task AppendDataAsync_Uses_The_Read_And_Write_Buffers_Correctly(int readBufferSize, int writeBufferSize, int fileSize, int expectedNumberOfWrites, int expectedNumberOfReads) { int numberOfReadsPerWrite = (int)Math.Ceiling((double)writeBufferSize / readBufferSize); var store = new TusDiskStore(_fixture.Path, false, new TusDiskBufferSize(writeBufferSize, readBufferSize)); var totalNumberOfWrites = 0; var totalNumberOfReads = 0; var numberOfReadsSinceLastWrite = 0; int totalBytesWritten = 0; var fileId = await store.CreateFileAsync(fileSize, null, CancellationToken.None); var requestStream = new RequestStreamFake(async(RequestStreamFake stream, byte[] bufferToFill, int offset, int count, CancellationToken cancellationToken) => { count.ShouldBe(readBufferSize); var bytesReadFromStream = await stream.ReadBackingStreamAsync(bufferToFill, offset, count, cancellationToken); // There should have been a write after the previous read. if (numberOfReadsSinceLastWrite > numberOfReadsPerWrite) { // Calculate the amount of data that should have been written to disk so far. var expectedFileSizeRightNow = CalculateExpectedFileSize(totalNumberOfReads, readBufferSize, writeBufferSize); // Assert that the size on disk is correct. GetLengthFromFileOnDisk().ShouldBe(expectedFileSizeRightNow); totalNumberOfWrites++; // Set to one as the write happened on the previous write, making this the second read since that write. numberOfReadsSinceLastWrite = 1; } numberOfReadsSinceLastWrite++; totalNumberOfReads++; totalBytesWritten += bytesReadFromStream; return(bytesReadFromStream); }, new byte[fileSize]); await store.AppendDataAsync(fileId, requestStream, CancellationToken.None); GetLengthFromFileOnDisk().ShouldBe(fileSize); totalNumberOfWrites++; // -1 due to the last read returning 0 bytes as the stream is then drained Assert.Equal(expectedNumberOfReads, totalNumberOfReads - 1); Assert.Equal(expectedNumberOfWrites, totalNumberOfWrites); long GetLengthFromFileOnDisk() { return(new FileInfo(Path.Combine(_fixture.Path, fileId)).Length); } }