Program.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using IES.ExamServer.DI;
  2. using IES.ExamServer.DI.SignalRHost;
  3. using IES.ExamServer.Filters;
  4. using Microsoft.AspNetCore.StaticFiles;
  5. using NLog.Extensions.Logging;
  6. using SkiaSharp;
  7. using System.Drawing;
  8. using System.Text;
  9. using System.Text.Encodings.Web;
  10. using System.Text.Unicode;
  11. using static System.Net.Mime.MediaTypeNames;
  12. using System.Diagnostics;
  13. using System.Security.Authentication;
  14. using Microsoft.Extensions.FileProviders;
  15. namespace IES.ExamServer.Server
  16. {
  17. public class Program
  18. {
  19. public async static Task Main(string[] args)
  20. {
  21. Console.OutputEncoding = Encoding.UTF8;
  22. var builder = WebApplication.CreateBuilder(args);
  23. // Add services to the container.
  24. builder.WebHost.ConfigureKestrel(serverOptions =>
  25. {
  26. // 配置支持的 SSL/TLS 协议版本
  27. serverOptions.ConfigureHttpsDefaults(httpsOptions =>
  28. {
  29. httpsOptions.SslProtocols = SslProtocols.Tls |
  30. SslProtocols.Tls11 |
  31. SslProtocols.Tls12 |
  32. SslProtocols.Tls13;
  33. });
  34. });
  35. string path = $"{builder.Environment.ContentRootPath}/Configs";
  36. // Add services to the container.
  37. builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
  38. // Add services to the container.
  39. builder.Services.AddControllersWithViews().AddJsonOptions(options =>
  40. {
  41. // 设置 JSON 序列化选项
  42. options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); // 允许所有 Unicode 字符
  43. options.JsonSerializerOptions.WriteIndented = true; // 格式化输出(可选)
  44. });
  45. builder.Services.AddHttpClient();
  46. builder.Services.AddSignalR();
  47. builder.Services.AddHttpContextAccessor();
  48. //此处能在Linux及MacOS运行,
  49. //Windows的路径是LocalApplicationData Path: C:\Users\john\AppData\Local
  50. //Linux的路径是LocalApplicationData Path: /home/john/.local/share,
  51. //MacOS 的路径LocalApplicationData Path: /Users/john/Library/Application Support
  52. string localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
  53. //string dbpath = $"{localAppDataPath}\\ExamServer\\LiteDB";
  54. string dbpath = Path.Combine(localAppDataPath, "ExamServer", "LiteDB");
  55. if (!System.IO.Directory.Exists(dbpath))
  56. {
  57. System.IO.Directory.CreateDirectory(dbpath);
  58. }
  59. string liteDBPath = $"Filename={dbpath}/data.db;Connection=shared";
  60. var connections_LiteDB = new List<LiteDBFactoryOptions>
  61. {
  62. new LiteDBFactoryOptions { Name = "Master", Connectionstring = liteDBPath}
  63. };
  64. builder.Services.AddLiteDB(connections_LiteDB);
  65. builder.Services.AddMemoryCache();
  66. // 注册 ConnectionService 为单例
  67. builder.Services.AddSingleton<CenterServiceConnectionService>();
  68. builder.Services.AddSingleton<ServiceInitializer>();
  69. // 注册 DataQueue 服务
  70. builder.Services.AddSingleton<DataQueue>();
  71. // 注册后台服务
  72. builder.Services.AddHostedService<SubjectPushService>();
  73. builder.Services.AddCors(options =>
  74. {
  75. //options.AddDefaultPolicy(
  76. //builder =>
  77. //{
  78. // builder.AllowAnyOrigin()
  79. // .AllowAnyHeader()
  80. // .AllowAnyMethod();
  81. //});
  82. options.AddPolicy("any", builder =>
  83. {
  84. //builder.SetIsOriginAllowed(x => true)
  85. //.AllowAnyMethod()
  86. //.AllowAnyHeader()
  87. //.AllowCredentials();
  88. builder.AllowAnyOrigin()
  89. .AllowAnyHeader()
  90. .AllowAnyMethod();
  91. });
  92. });
  93. builder.Services.AddMvcFilter<AuthTokenActionFilter>();
  94. // 添加自定义日志提供程序
  95. //builder.Logging.ClearProviders();
  96. //bool enableConsoleOutput = true;
  97. //builder.Logging.AddProvider(new CustomFileLoggerProvider(Path.Combine(Directory.GetCurrentDirectory(), "Logs"), enableConsoleOutput));
  98. // 添加日志服务
  99. builder.Logging.ClearProviders();
  100. builder.Logging.AddNLog();
  101. builder.Services.AddHostedService<SignalRCloudClientHub>();
  102. var app = builder.Build();
  103. app.UseDefaultFiles();
  104. //var contentTypeProvider = new FileExtensionContentTypeProvider();
  105. //contentTypeProvider.Mappings[".txt"] = "text/plain";
  106. //contentTypeProvider.Mappings[".jpg"] = "image/jpeg";
  107. //contentTypeProvider.Mappings[".jpeg"] = "image/jpeg";
  108. //contentTypeProvider.Mappings[".png"] = "image/png";
  109. //contentTypeProvider.Mappings[".html"] = "text/html";
  110. //contentTypeProvider.Mappings[".js"] = "application/javascript";
  111. //contentTypeProvider.Mappings[".css"] = "text/css";
  112. //contentTypeProvider.Mappings[".mp4"] = "video/mp4";
  113. //contentTypeProvider.Mappings[".mp3"] = "audio/mpeg";
  114. //contentTypeProvider.Mappings[".json"] = "application/json";
  115. //contentTypeProvider.Mappings[".pdf"] = "application/pdf";
  116. string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
  117. if (!Directory.Exists(packagePath))
  118. {
  119. Directory.CreateDirectory(packagePath);
  120. }
  121. //会自动处理文件夹下的子文件夹及文件映射关系。
  122. /*
  123. 请求 URL 映射到的文件路径
  124. https://localhost/data/data.json C:\Users\YourUser\AppData\Local\ExamData\data.json
  125. https://localhost/data/abc/a.json C:\Users\YourUser\AppData\Local\ExamData\abc\a.json
  126. https://localhost/data/123/1.json C:\Users\YourUser\AppData\Local\ExamData\123\1.json
  127. */
  128. string uploadPath = Path.Combine(localAppDataPath, "ExamServer", "Upload");
  129. if (!Directory.Exists(uploadPath))
  130. {
  131. Directory.CreateDirectory(uploadPath);
  132. }
  133. app.UseStaticFiles(new StaticFileOptions
  134. {
  135. FileProvider = new PhysicalFileProvider(uploadPath),
  136. RequestPath = "/upload" // 映射请求路径,学生上传文件
  137. });
  138. string answerPath = Path.Combine(localAppDataPath, "ExamServer", "Answer");
  139. if (!Directory.Exists(answerPath))
  140. {
  141. Directory.CreateDirectory(answerPath);
  142. }
  143. app.UseStaticFiles(new StaticFileOptions
  144. {
  145. FileProvider = new PhysicalFileProvider(answerPath),
  146. RequestPath = "/answer" // 映射请求路径,学生作答文件
  147. });
  148. app.UseStaticFiles();
  149. // Configure the HTTP request pipeline.
  150. app.UseHttpsRedirection();
  151. app.UseRouting();
  152. app.UseCors("any");
  153. app.UseAuthorization();
  154. app.MapControllers();
  155. app.MapFallbackToFile("/index.html");
  156. app.MapHub<SignalRExamServerHub>("/signalr/exam").RequireCors("any");
  157. var connectionManager = app.Services.GetRequiredService<ServiceInitializer>();
  158. await connectionManager.InitializeAsync();
  159. await app.RunAsync();
  160. }
  161. }
  162. }