public static async Task SaveFileAsync(ITusFile file, IHostingEnvironment env) { CancellationTokenSource source = new CancellationTokenSource(); CancellationToken token = source.Token; var metadata = await file.GetMetadataAsync(token); var fileName = Path.GetRandomFileName(); if (metadata.ContainsKey("filename")) { fileName = metadata["filename"].GetString(Encoding.UTF8); } var filePath = Path.Combine(env.ContentRootPath, "arquivos", fileName); CreateDirectory(Path.Combine(env.ContentRootPath, "arquivos")); using (var stream = await file.GetContentAsync(token)) { using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { stream.CopyTo(fileStream); } } }
/// <summary> /// Persist the uploaded file data to db /// </summary> private async Task <gFileItem> PersistMetaData(FileCompleteContext ctx) { var gUserResponse = await _fileMngClient.GetUserAsync(new gUserRequest()); if (gUserResponse == null) { _logger.LogError("Unknown error occured while requesting user info"); ctx.HttpContext.Response.StatusCode = 400; return(null); } if (gUserResponse.Status.Status != Protos.RequestStatus.Success) { _logger.LogError(gUserResponse.Status.Message); ctx.HttpContext.Response.StatusCode = 400; return(null); } ITusFile file = await((ITusReadableStore)ctx.Store).GetFileAsync(ctx.FileId, ctx.CancellationToken); var metadata = await file.GetMetadataAsync(ctx.CancellationToken); gFileItem fileitem = new gFileItem() { Id = Helpers.GenerateUniqueId(), TusId = ctx.FileId, UserId = gUserResponse.User.Id, Size = uint.Parse(new FileInfo(Path.Combine(_uploadOpts.CurrentValue.UploadPath, file.Id)).Length.ToString()), Name = metadata["name"].GetString(Encoding.UTF8), MimeType = metadata["contentType"].GetString(Encoding.UTF8), // file with no folderid is placed in the virtual root folder FolderId = metadata["folderId"].GetString(Encoding.UTF8) == "root" ? null : metadata["folderId"].GetString(Encoding.UTF8), Extension = Helpers.GetFileExtension(metadata["contentType"].GetString(Encoding.UTF8)) ?? string.Empty, StorageServerId = metadata["serverId"].GetString(Encoding.UTF8), CreatedAt = Timestamp.FromDateTime(DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)), LastModified = Timestamp.FromDateTime(DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)), Status = Protos.ItemStatus.Visible }; // send the uploaded file info to the main app gFileItemResponse response = await _fileMngClient.SaveFileAsync(new gFileItemRequest() { FileItem = fileitem }); if (response == null) { _logger.LogError("No response has been received from the server.", ErrorOrigin.Server); return(null); } if (response.Status.Status != Protos.RequestStatus.Success) { _logger.LogError("An error has been returned from server call: " + response.Status.Message); return(null); } return(response.FileItem); }
/// <summary> /// Check if the <see cref="ITusFile"/> has been completely uploaded. /// </summary> /// <param name="file">The file to check</param> /// <param name="store">The store responsible for handling the file</param> /// <param name="cancellationToken">The cancellation token to use when cancelling</param> /// <returns>True if the file is completed, otherwise false</returns> public static async Task <bool> IsCompleteAsync(this ITusFile file, ITusStore store, CancellationToken cancellationToken) { var length = store.GetUploadLengthAsync(file.Id, cancellationToken); var offset = store.GetUploadOffsetAsync(file.Id, cancellationToken); await Task.WhenAll(length, offset); return(length.Result == offset.Result); }
private async Task DoSomeProcessing(ITusFile file, Dictionary <string, tusdotnet.Models.Metadata> metadata) { var guid = Guid.ParseExact(file.Id, "N"); _logger.LogInformation($"Publish message with: FileId = {file.Id}, Name = {metadata.GetValueOrDefault("filename", null)?.GetString(Encoding.UTF8)}, Type = {metadata.GetValueOrDefault("filetype", null)?.GetString(Encoding.UTF8)}"); await _messageQueue.Publish <IVideoUploadedEvent>(new VideoUploadedEvent { FileId = guid, Name = metadata.GetValueOrDefault("filename", null)?.GetString(Encoding.UTF8), Type = metadata.GetValueOrDefault("filetype", null)?.GetString(Encoding.UTF8) }); await _messageQueue.Publish <IVideoUploadedForCatalogEvent>(new VideoUploadedForCatalogEvent { FileId = guid, Name = metadata.GetValueOrDefault("filename", null)?.GetString(Encoding.UTF8), Type = metadata.GetValueOrDefault("filetype", null)?.GetString(Encoding.UTF8) }); }
public async Task OnFileCompleteAsync(FileCompleteContext context) { ITusFile file = await context.GetFileAsync(); _logger.LogInformation($"Fileupload completed: ${file.Id}"); var metadata = await file.GetMetadataAsync(context.CancellationToken); var metadataInString = ""; foreach (var item in metadata) { if (metadataInString.Length != 0) { metadataInString += ", "; } metadataInString += $"\"{item.Key}:{item.Value.GetString(Encoding.UTF8)}\""; } _logger.LogInformation($"Fileupload completed: {metadataInString}"); await DoSomeProcessing(file, metadata); await Task.CompletedTask; }
public static async Task HandleRoute(HttpContext context) { DefaultTusConfiguration config = context.RequestServices.GetRequiredService <DefaultTusConfiguration>(); if (!(config.Store is ITusReadableStore store)) { return; } string fileId = (string)context.Request.RouteValues["fileId"]; ITusFile file = await store.GetFileAsync(fileId, context.RequestAborted); if (file == null) { context.Response.StatusCode = 404; await context.Response.WriteAsync($"File with id {fileId} was not found.", context.RequestAborted); return; } System.IO.Stream fileStream = await file.GetContentAsync(context.RequestAborted); Dictionary <string, Metadata> metadata = await file.GetMetadataAsync(context.RequestAborted); context.Response.ContentType = GetContentTypeOrDefault(metadata); context.Response.ContentLength = fileStream.Length; if (metadata.TryGetValue("name", out var nameMeta)) { context.Response.Headers.Add("Content-Disposition", new[] { $"attachment; filename=\"{nameMeta.GetString(Encoding.UTF8)}\"" }); } using (fileStream) await fileStream.CopyToAsync(context.Response.Body, 81920, context.RequestAborted); }
// Generates thumbnail from an image and returns its relative path private async Task <string> GenerateImageThumbnailAsync( ITusFile file, string fileExtension, string storePath, string userName, CancellationToken ct, int height = 400, int width = 400) { var thumbnailDirectory = Path.Combine(storePath, "thumbnails"); var thumbnailFilePath = Path.Combine(storePath, "thumbnails", $"{file.Id}_{width}x{height}_thumbnail{fileExtension}"); // Creates directory if it does not exist... Directory.CreateDirectory(thumbnailDirectory); using (Image image = Image.Load(await file.GetContentAsync(ct))) { image.Mutate(x => x.Resize(width, height)); image.Save(thumbnailFilePath); return(thumbnailFilePath); } }
// 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"); } } } });
private async Task <bool> TusIsFileTypeVerifiedAsync(ITusFile file, string fileName, CancellationToken cancellationToken) { // If you require a check on specific characters in the IsValidFileExtensionAndSignature // method, supply the characters in the _allowedChars field. byte[] _allowedChars = { }; var ext = Path.GetExtension(fileName).ToLowerInvariant(); if (string.IsNullOrEmpty(ext)) { return(false); } // For more file signatures, see the File Signatures Database (https://www.filesignatures.net/) // and the official specifications for the file types you wish to add. Dictionary <string, List <byte[]> > _fileSignature = new Dictionary <string, List <byte[]> > { { ".gif", new List <byte[]> { new byte[] { 0x47, 0x49, 0x46, 0x38 } } }, { ".bmp", new List <byte[]> { new byte[] { 0x42, 0x4D } } }, { ".png", new List <byte[]> { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } }, { ".jpeg", new List <byte[]> { new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 }, new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 }, new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 }, } }, { ".jpg", new List <byte[]> { new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 }, new byte[] { 0xFF, 0xD8, 0xFF, 0xE1 }, new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 }, } }, { ".3gp", new List <byte[]> { new byte[] { 0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70 }, new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70 }, } }, { ".avi", new List <byte[]> { new byte[] { 0x52, 0x49, 0x46, 0x46 } } }, { ".flv", new List <byte[]> { new byte[] { 0x46, 0x4C, 0x56 } } }, { ".wmv", new List <byte[]> { new byte[] { 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11 } } }, { ".mpg", new List <byte[]> { new byte[] { 0x00, 0x00, 0x01, 0xBA }, new byte[] { 0x00, 0x00, 0x01, 0xB3 }, } }, { ".mp4", new List <byte[]> { new byte[] { 0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D }, new byte[] { 0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x53, 0x4E, 0x56 }, new byte[] { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D }, new byte[] { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x53, 0x4E, 0x56 }, new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D }, new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x53, 0x4E, 0x56 }, } }, { ".mkv", new List <byte[]> { new byte[] { 0x1A, 0x45, 0xDF, 0xA3, 0x93, 0x42, 0x82, 0x88 } } }, { ".wma", new List <byte[]> { new byte[] { 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11 } } }, { ".mp3", new List <byte[]> { new byte[] { 0x49, 0x44, 0x33 } } }, { ".pdf", new List <byte[]> { new byte[] { 0x25, 0x50, 0x44, 0x46 } } }, { ".rtf", new List <byte[]> { new byte[] { 0x7B, 0x5C, 0x72, 0x74, 0x66, 0x31 } } }, { ".doc", new List <byte[]> { new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, new byte[] { 0x0D, 0x44, 0x4F, 0x43 }, new byte[] { 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1, 0x00 }, new byte[] { 0xDB, 0xA5, 0x2D, 0x00 }, new byte[] { 0xEC, 0xA5, 0xC1, 0x00 }, } }, { ".docx", new List <byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 }, new byte[] { 0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00 }, } }, { ".xls", new List <byte[]> { new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, new byte[] { 0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00 }, new byte[] { 0xFD, 0xFF, 0xFF, 0xFF, 0x10 }, new byte[] { 0xFD, 0xFF, 0xFF, 0xFF, 0x1F }, new byte[] { 0xFD, 0xFF, 0xFF, 0xFF, 0x22 }, new byte[] { 0xFD, 0xFF, 0xFF, 0xFF, 0x23 }, new byte[] { 0xFD, 0xFF, 0xFF, 0xFF, 0x28 }, new byte[] { 0xFD, 0xFF, 0xFF, 0xFF, 0x29 }, } }, { ".xlsx", new List <byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 }, new byte[] { 0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00 }, } }, { ".zip", new List <byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 }, new byte[] { 0x50, 0x4B, 0x4C, 0x49, 0x54, 0x45 }, new byte[] { 0x50, 0x4B, 0x53, 0x70, 0x58 }, new byte[] { 0x50, 0x4B, 0x05, 0x06 }, new byte[] { 0x50, 0x4B, 0x07, 0x08 }, new byte[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70 }, } }, { ".rar", new List <byte[]> { new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 } } }, { ".7z", new List <byte[]> { new byte[] { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C } } }, }; using (var stream = await file.GetContentAsync(cancellationToken)) using (var reader = new BinaryReader(stream)) { if (ext.Equals(".txt") || ext.Equals(".csv") || ext.Equals(".prn") || ext.Equals(".svg")) { if (_allowedChars.Length == 0) { // Limits characters to ASCII encoding. for (var i = 0; i < stream.Length; i++) { if (reader.ReadByte() > sbyte.MaxValue) { return(false); } } } else { // Limits characters to ASCII encoding and // values of the _allowedChars array. for (var i = 0; i < stream.Length; i++) { var b = reader.ReadByte(); if (b > sbyte.MaxValue || !_allowedChars.Contains(b)) { return(false); } } } return(true); } // Uncomment the following code block if you must permit // files whose signature isn't provided in the _fileSignature // dictionary. We recommend that you add file signatures // for files (when possible) for all file types you intend // to allow on the system and perform the file signature // check. /* * if (!_fileSignature.ContainsKey(ext)) * { * return true; * } */ // File signature check // -------------------- // With the file signatures provided in the _fileSignature // dictionary, the following code tests the input content's // file signature. List <byte[]> signatures = _fileSignature.TryGetValue(ext, out signatures) ? _fileSignature[ext] : null; if (signatures == null) { return(false); } var headerBytes = reader.ReadBytes(signatures.Max(m => m.Length)); return(signatures.Any(signature => headerBytes.Take(signature.Length).SequenceEqual(signature))); } }
public async Task SaveTusFileInfoAsync(ITusFile file, SiteTypeEnum siteType, string refreshToken, UploadLocationEnum location, UploadLinkAccessibilityEnum linkAccessibility, CancellationToken cancellationToken) { var metadata = await file.GetMetadataAsync(cancellationToken); string name = metadata["name"].GetString(Encoding.UTF8); string type = metadata["type"].GetString(Encoding.UTF8); using (var scope = Services.CreateScope()) { var httpContextAccessor = scope.ServiceProvider .GetRequiredService <IHttpContextAccessor>(); var context = scope.ServiceProvider .GetRequiredService <DataContext>(); var logger = scope.ServiceProvider .GetRequiredService <IActivityLogger>(); var token = context.Tokens.SingleOrDefault(x => x.RefreshToken == refreshToken); var user = token.CreatedBy; var storePath = Path.Combine(UploadFolderName, user.UserName); var extension = Path.GetExtension(name); var fileName = file.Id; var filePublicName = name; var mimeType = type; var fileRelativePath = Path.Combine(storePath, fileName); long size = 0; string fileThumbnailPath = ""; var fileType = TusCheckFileType(type); if (location == UploadLocationEnum.LocalHost) { size = new FileInfo(Path.Combine(UploadFolderName, user.UserName, fileName)).Length; fileThumbnailPath = fileType == AttachmentTypeEnum.Photo ? await GenerateImageThumbnailAsync(file, extension, storePath, user.UserName, cancellationToken) : ""; } if (location == UploadLocationEnum.FtpServer) { // create an FTP client FtpClient client = new FtpClient(_baseUri, _port, _username, _password); // begin connecting to the server await client.ConnectAsync(); size = await client.GetFileSizeAsync($"{storePath}/{fileName}"); // await client.DisconnectAsync(); } var site = await context.Sites.SingleOrDefaultAsync(x => x.SiteType == siteType); user.CreatedAttachments.Add(new Attachment { SiteId = site.Id, UploadLocation = location, Type = fileType, RelativePath = fileRelativePath, ThumbnailPath = fileThumbnailPath, MimeType = mimeType, FileName = fileName, PublicFileName = filePublicName, FileExtension = extension, FileSize = size, LinkAccessibility = linkAccessibility }); var success = await context.SaveChangesAsync() > 0; if (success) { await logger.LogActivity( site.Id, ActivityCodeEnum.AttachmentAdd, ActivitySeverityEnum.Medium, ActivityObjectEnum.Attachemnt, $"The {fileType} file with the name {fileName} has been uploaded"); } else { throw new Exception("Problem saving file information in database!"); } } }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHttpContextAccessor httpContextAccessor, ILogger <Startup> logger, ITusUploadUtils tusUploadUtils, IOptions <FtpServerSettings> config) { if (env.IsDevelopment()) { app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCultureIgnoreCase), appBuilder => { // Custom API Error handler appBuilder.UseMiddleware <APIErrorHandlingMiddleware>(); } ); app.UseWhen(ctx => !ctx.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCultureIgnoreCase), appBuilder => { // Default mvc error handler appBuilder.UseDeveloperExceptionPage(); } ); } else { app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCultureIgnoreCase), appBuilder => { // Custom API Error handler appBuilder.UseMiddleware <APIErrorHandlingMiddleware>(); } ); app.UseWhen(ctx => !ctx.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCultureIgnoreCase), appBuilder => { // Default mvc error handler appBuilder.UseExceptionHandler("/Home/Error"); } ); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } //app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseCors("CorsPolicy"); app.UseAuthentication(); app.UseAuthorization(); // To use FTPServer as the storage you must use TusDiskStore instead of CustomTusDiskStore // if you want to use localhost as the storage without config param var uploadLocation = UploadLocationEnum.LocalHost; app.UseTus(httpContext => new DefaultTusConfiguration { // Use TusDiskStore instead of CustomTusDiskStore if you want to use localhost as the storage without config param Store = new TusDiskStore(tusUploadUtils.GetStorePath("uploads", uploadLocation), true, new TusDiskBufferSize(1024 * 1024 * 5, 1024 * 1024 * 5)), // On what url should we listen for uploads? UrlPath = "/api/v1/attachments/add-private-media", Events = new Events { OnAuthorizeAsync = eventContext => { var refreshToken = httpContextAccessor.HttpContext.Request.Cookies["refreshToken"]; if (refreshToken == null) { 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") // { // 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: break; case IntentType.ConcatenateFiles: break; case IntentType.WriteFile: break; case IntentType.DeleteFile: break; case IntentType.GetFileInfo: break; case IntentType.GetOptions: break; default: break; } return(Task.CompletedTask); }, OnBeforeCreateAsync = async ctx => { var storePath = tusUploadUtils.GetStorePath("uploads", uploadLocation); // If localhost is the storage if (uploadLocation == UploadLocationEnum.LocalHost) { // Create temp directory if it does not exist... Directory.CreateDirectory(storePath); } // If FTP server is the storage if (uploadLocation == UploadLocationEnum.FtpServer) { // create an FTP client FtpClient client = new FtpClient(config.Value.ServerUri, config.Value.ServerPort, config.Value.ServerUsername, config.Value.ServerPassword); // Connecting to the server await client.ConnectAsync(); // check if a folder doesn't exist if (!await client.DirectoryExistsAsync(storePath)) { await client.CreateDirectoryAsync(storePath); } } if (!ctx.Metadata.ContainsKey("name")) { ctx.FailRequest("name metadata must be specified. "); } if (!ctx.Metadata.ContainsKey("type")) { ctx.FailRequest("filetype metadata must be specified. "); } if (!await tusUploadUtils.IsFileTypeAllowed(ctx.Metadata["type"].GetString(Encoding.UTF8), SiteTypeEnum.Blog)) { ctx.FailRequest("Filetype is not allowed!"); } }, OnFileCompleteAsync = async eventContext => { ITusFile file = await eventContext.GetFileAsync(); var refreshToken = httpContextAccessor.HttpContext.Request.Cookies["refreshToken"]; // Saving file information into database await tusUploadUtils.SaveTusFileInfoAsync(file, SiteTypeEnum.Blog, refreshToken, uploadLocation, UploadLinkAccessibilityEnum.Private, eventContext.CancellationToken); // If FTP server is the storage if (uploadLocation == UploadLocationEnum.FtpServer) { // create an FTP client FtpClient client = new FtpClient(config.Value.ServerUri, config.Value.ServerPort, config.Value.ServerUsername, config.Value.ServerPassword); // Connecting to the server await client.DisconnectAsync(); } }, } }); app.UseTus(httpContext => new DefaultTusConfiguration { // Use TusDiskStore instead of CustomTusDiskStore if you want to use localhost as the storage without config param Store = new TusDiskStore( tusUploadUtils.GetStorePath("uploads", uploadLocation, UploadLinkAccessibilityEnum.Private), true, new TusDiskBufferSize(1024 * 1024 * 5, 1024 * 1024 * 5)), // On what url should we listen for uploads? UrlPath = "/api/v1/attachments/add-public-media", Events = new Events { OnAuthorizeAsync = eventContext => { var refreshToken = httpContextAccessor.HttpContext.Request.Cookies["refreshToken"]; if (refreshToken == null) { 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") // { // 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: break; case IntentType.ConcatenateFiles: break; case IntentType.WriteFile: break; case IntentType.DeleteFile: break; case IntentType.GetFileInfo: break; case IntentType.GetOptions: break; default: break; } return(Task.CompletedTask); }, OnBeforeCreateAsync = async ctx => { var storePath = tusUploadUtils.GetStorePath( "uploads", uploadLocation, UploadLinkAccessibilityEnum.Private); // If localhost is the storage if (uploadLocation == UploadLocationEnum.LocalHost) { // Create temp directory if it does not exist... Directory.CreateDirectory(storePath); } // If FTP server is the storage if (uploadLocation == UploadLocationEnum.FtpServer) { // create an FTP client FtpClient client = new FtpClient(config.Value.ServerUri, config.Value.ServerPort, config.Value.ServerUsername, config.Value.ServerPassword); // Connecting to the server await client.ConnectAsync(); // check if a folder doesn't exist if (!await client.DirectoryExistsAsync(storePath)) { await client.CreateDirectoryAsync(storePath); } } if (!ctx.Metadata.ContainsKey("name")) { ctx.FailRequest("name metadata must be specified. "); } if (!ctx.Metadata.ContainsKey("type")) { ctx.FailRequest("filetype metadata must be specified. "); } if (!await tusUploadUtils.IsFileTypeAllowed(ctx.Metadata["type"].GetString(Encoding.UTF8), SiteTypeEnum.Blog)) { ctx.FailRequest("Filetype is not allowed!"); } }, OnFileCompleteAsync = async eventContext => { ITusFile file = await eventContext.GetFileAsync(); var refreshToken = httpContextAccessor.HttpContext.Request.Cookies["refreshToken"]; // Saving file information into database await tusUploadUtils.SaveTusFileInfoAsync(file, SiteTypeEnum.Blog, refreshToken, uploadLocation, UploadLinkAccessibilityEnum.Public, eventContext.CancellationToken); // If FTP server is the storage if (uploadLocation == UploadLocationEnum.FtpServer) { // create an FTP client FtpClient client = new FtpClient(config.Value.ServerUri, config.Value.ServerPort, config.Value.ServerUsername, config.Value.ServerPassword); // Connecting to the server await client.DisconnectAsync(); } }, } }); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }