|
@@ -15,6 +15,8 @@ using System.Net.Http;
|
|
|
using System.Net.Http.Json;
|
|
|
using System.Text.Json;
|
|
|
using System.Text.Json.Nodes;
|
|
|
+using System.Text.RegularExpressions;
|
|
|
+using static System.Reflection.Metadata.BlobBuilder;
|
|
|
|
|
|
namespace IES.ExamServer.Controllers
|
|
|
{
|
|
@@ -57,7 +59,7 @@ namespace IES.ExamServer.Controllers
|
|
|
return Ok();
|
|
|
}
|
|
|
[HttpPost("download-package")]
|
|
|
- [AuthToken("admin","teacher", "visitor")]
|
|
|
+ [AuthToken("admin", "teacher", "visitor")]
|
|
|
public async Task<IActionResult> DownloadPackage(JsonNode json)
|
|
|
{
|
|
|
//C#.NET 6 后端与前端流式通信
|
|
@@ -77,13 +79,14 @@ namespace IES.ExamServer.Controllers
|
|
|
*/
|
|
|
//如果要访问中心,则需要教师登录联网。
|
|
|
var token = GetAuthTokenInfo();
|
|
|
- if (token.scope.Equals(ExamConstant.ScopeTeacher))
|
|
|
+ if (token.scope.Equals(ExamConstant.ScopeTeacher) || token.scope.Equals(ExamConstant.ScopeVisitor))
|
|
|
{
|
|
|
- if (_connectionService.centerIsConnected)
|
|
|
+ if (_connectionService.centerIsConnected)
|
|
|
{
|
|
|
Teacher? teacher = _liteDBFactory.GetLiteDatabase().GetCollection<Teacher>().FindOne(x => x.id!.Equals(token.id));
|
|
|
string id = $"{json["evaluationId"]}";
|
|
|
- EvaluationClient evaluationClient= _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id));
|
|
|
+ string shortCode = $"{json["shortCode"]}";
|
|
|
+ EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id) && x.shortCode!.Equals(shortCode));
|
|
|
if (teacher != null && evaluationClient!= null)
|
|
|
{
|
|
|
string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
|
|
@@ -109,17 +112,16 @@ namespace IES.ExamServer.Controllers
|
|
|
url = $"{jsonNode["url"]}";
|
|
|
}
|
|
|
}
|
|
|
- var httpClient= _httpClientFactory.CreateClient();
|
|
|
+ var httpClient = _httpClientFactory.CreateClient();
|
|
|
string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
|
|
|
string evaluationPath = Path.Combine(packagePath, evaluationClient.id!);
|
|
|
string evaluationDataPath = Path.Combine(evaluationPath, "data");
|
|
|
- if (!Directory.Exists(evaluationDataPath))
|
|
|
+ if (!Directory.Exists(evaluationDataPath))
|
|
|
{
|
|
|
Directory.CreateDirectory(evaluationDataPath);
|
|
|
}
|
|
|
-
|
|
|
string evaluationData = string.Empty;
|
|
|
- if ($"{json["data"]}".Equals("1"))
|
|
|
+ if ($"{json["data"]}".Equals("1"))
|
|
|
{
|
|
|
{
|
|
|
string evaluationUrl = $"{url}/{cnt}/package/{json["evaluationId"]}/data/evaluation.json?{sas}";
|
|
@@ -129,7 +131,7 @@ namespace IES.ExamServer.Controllers
|
|
|
string path_evaluation = Path.Combine(evaluationDataPath, "evaluation.json");
|
|
|
await System.IO.File.WriteAllTextAsync(path_evaluation, content);
|
|
|
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
{
|
|
|
//source.json
|
|
@@ -143,14 +145,14 @@ namespace IES.ExamServer.Controllers
|
|
|
if ($"{json["groupList"]}".Equals("1"))
|
|
|
{
|
|
|
string grouplistUrl = $"{url}/{cnt}/package/{json["evaluationId"]}/data/grouplist.json?{sas}";
|
|
|
- HttpResponseMessage groupListMessage = await httpClient.GetAsync(grouplistUrl);
|
|
|
+ HttpResponseMessage groupListMessage = await httpClient.GetAsync(grouplistUrl);
|
|
|
var content = await groupListMessage.Content.ReadAsStringAsync();
|
|
|
string path_groupList = Path.Combine(evaluationDataPath, "grouplist.json");
|
|
|
await System.IO.File.WriteAllTextAsync(path_groupList, content);
|
|
|
}
|
|
|
if ($"{json["blob"]}".Equals("1"))
|
|
|
{
|
|
|
- if (string.IsNullOrEmpty(evaluationData))
|
|
|
+ if (string.IsNullOrEmpty(evaluationData))
|
|
|
{
|
|
|
string evaluationUrl = $"{url}/{cnt}/package/{json["evaluationId"]}/data/evaluation.json?{sas}";
|
|
|
HttpResponseMessage dataMessage = await httpClient.GetAsync(evaluationUrl);
|
|
@@ -167,7 +169,8 @@ namespace IES.ExamServer.Controllers
|
|
|
{
|
|
|
Directory.CreateDirectory(path_paper);
|
|
|
}
|
|
|
- var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 50 };
|
|
|
+ //最多开启10个线程并行下载
|
|
|
+ var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 10 };
|
|
|
// 使用 Parallel.ForEachAsync 并行处理每个 blob
|
|
|
await Parallel.ForEachAsync(evaluationPaper.blobs, parallelOptions, async (blob, cancellationToken) =>
|
|
|
{
|
|
@@ -179,12 +182,21 @@ namespace IES.ExamServer.Controllers
|
|
|
{
|
|
|
byte[] bytes = await blobMessage.Content.ReadAsByteArrayAsync(cancellationToken);
|
|
|
string? fileName = Path.GetFileName(blob.path);
|
|
|
- if (fileName != null)
|
|
|
+ string? fileNameWithoutExtension = Path.GetFileNameWithoutExtension(blob.path);
|
|
|
+ string? extension = Path.GetExtension(blob.path);
|
|
|
+ if (extension!=null)
|
|
|
{
|
|
|
- await System.IO.File.WriteAllBytesAsync(Path.Combine(path_paper, fileName), bytes, cancellationToken);
|
|
|
+ if (extension.Equals(extension.ToUpper()))
|
|
|
+ {
|
|
|
+ await System.IO.File.WriteAllBytesAsync(Path.Combine(path_paper, $"{fileNameWithoutExtension!}_1{extension}"), bytes, cancellationToken);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ await System.IO.File.WriteAllBytesAsync(Path.Combine(path_paper, fileName!), bytes, cancellationToken);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- else
|
|
|
+ else
|
|
|
{
|
|
|
string? error = await blobMessage.Content.ReadAsStringAsync(cancellationToken);
|
|
|
Console.WriteLine($"Error downloading {blob.path},{blobMessage.StatusCode},{error}");
|
|
@@ -224,11 +236,34 @@ namespace IES.ExamServer.Controllers
|
|
|
// }
|
|
|
//}
|
|
|
}
|
|
|
+
|
|
|
//下载完成后,对数据进行检查,然后在加密压缩。
|
|
|
+ string zipPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "zip");
|
|
|
+ if (!Directory.Exists(zipPath))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(zipPath);
|
|
|
+ }
|
|
|
+ //判断文件包的压缩包是否存在。
|
|
|
+ string zipFilePath = Path.Combine(zipPath, $"{evaluationClient.id}-{evaluationClient.blobHash}.zip");
|
|
|
+ ZipHelper.CreatePasswordProtectedZip(evaluationPath, zipFilePath, evaluationClient.openCode!);
|
|
|
+ return Ok(new { code = 200, msg = "下载成功!", url = zipFilePath });
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ string teacherMsg = teacher==null ? "未找到教师信息" : "";
|
|
|
+ string evaluationMsg = evaluationClient==null ? "未找到评测信息" : "";
|
|
|
+ return Ok(new { code = 1, msg = $"用户信息或未找到评测信息!{teacherMsg}{evaluationMsg}" });
|
|
|
}
|
|
|
}
|
|
|
+ else {
|
|
|
+ return Ok(new { code = 2, msg = "云端数据中心未连接" });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Ok(new { code = 3, msg = "请使用教师或访客账号登录!" });
|
|
|
}
|
|
|
- return Ok();
|
|
|
+
|
|
|
}
|
|
|
[HttpPost("check-evaluation")]
|
|
|
[AuthToken("admin", "teacher", "visitor")]
|
|
@@ -417,12 +452,14 @@ namespace IES.ExamServer.Controllers
|
|
|
//校验本地文件数据
|
|
|
string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
|
|
|
string zipPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "zip");
|
|
|
+ string evaluationPath = Path.Combine(packagePath, evaluationLocal.id!);
|
|
|
if (!Directory.Exists(packagePath))
|
|
|
{
|
|
|
Directory.CreateDirectory(packagePath);
|
|
|
}
|
|
|
+
|
|
|
//判断文件包的压缩包是否存在。
|
|
|
- if (!System.IO.File.Exists(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal}.zip")))
|
|
|
+ if (!System.IO.File.Exists(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal.blobHash}.zip")))
|
|
|
{
|
|
|
blob=1;//压缩包不存在
|
|
|
msg_status=Constant._Message_status_error;
|
|
@@ -434,8 +471,9 @@ namespace IES.ExamServer.Controllers
|
|
|
msg_status=Constant._Message_status_success;
|
|
|
checkTotal++;
|
|
|
checkSuccess++;
|
|
|
+ FileHelper.DeleteFolder(evaluationPath);
|
|
|
//解压操作。
|
|
|
- var extractRes= ZipHelper.ExtractPasswordProtectedZip(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal}.zip"), packagePath, evaluationLocal.openCode!);
|
|
|
+ var extractRes = ZipHelper.ExtractPasswordProtectedZip(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal.blobHash}.zip"), evaluationPath, evaluationLocal.openCode!);
|
|
|
if (extractRes.res)
|
|
|
{
|
|
|
checkTotal++;
|
|
@@ -449,8 +487,6 @@ namespace IES.ExamServer.Controllers
|
|
|
checkError++;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- string evaluationPath = Path.Combine(packagePath, evaluationLocal.id!);
|
|
|
string evaluationDataPath = Path.Combine(evaluationPath, "data");
|
|
|
|
|
|
string path_groupList = Path.Combine(evaluationDataPath, "groupList.json");
|
|
@@ -559,7 +595,7 @@ namespace IES.ExamServer.Controllers
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
-
|
|
|
+ string pattern = @"paper/[^/]+/([^/]+/[^/]+\.[^/]+)";
|
|
|
foreach (var evaluationExam in evaluationExams!)
|
|
|
{
|
|
|
string path_papers = Path.Combine(evaluationPath, "papers");
|
|
@@ -575,19 +611,40 @@ namespace IES.ExamServer.Controllers
|
|
|
msg_status=Constant._Message_status_info;
|
|
|
if (!string.IsNullOrWhiteSpace(blobInfo.path))
|
|
|
{
|
|
|
+ // exam/57de4dfe-944e-6d5a-98bb-6803b386f8c1/paper/subject_painting/4cce6c82-5e17-72e7-8e53-a2c45354b4a1/0abe9a37-90f8-baa9-f188-3f19574a880b.json
|
|
|
+
|
|
|
|
|
|
- var file = papers_files.Find(x => x.Contains(blobInfo.path));
|
|
|
- if (file!=null)
|
|
|
+ Match match = Regex.Match(blobInfo.path, pattern);
|
|
|
+ if (match.Success)
|
|
|
{
|
|
|
- msg_status=1;
|
|
|
- msg_status=Constant._Message_status_success;
|
|
|
+ string result = match.Groups[1].Value.Replace("/", "\\");
|
|
|
+ var file = papers_files.Find(x => x.Contains(result));
|
|
|
+ if (file!=null)
|
|
|
+ {
|
|
|
+ msg_status=1;
|
|
|
+ msg_status=Constant._Message_status_success;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ msg_status=Constant._Message_status_error;
|
|
|
+ paper_error_count++;
|
|
|
+ }
|
|
|
+
|
|
|
+ //if (result.EndsWith("mp4", StringComparison.OrdinalIgnoreCase))
|
|
|
+ //{
|
|
|
+ // Console.WriteLine(result); // 输出: 4cce6c82-5e17-72e7-8e53-a2c45354b4a1/0abe9a37-90f8-baa9-f188-3f19574a880b.json
|
|
|
+ //}
|
|
|
+
|
|
|
}
|
|
|
- else
|
|
|
+ else
|
|
|
{
|
|
|
msg_status=Constant._Message_status_error;
|
|
|
paper_error_count++;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -659,18 +716,7 @@ namespace IES.ExamServer.Controllers
|
|
|
content=$"检查到评测试卷需要更新。[{blobSize}]"
|
|
|
});
|
|
|
}
|
|
|
- //if (webview==1)
|
|
|
- //{
|
|
|
- // await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
- // new MessageContent
|
|
|
- // {
|
|
|
- // dataId=evaluationLocal.id,
|
|
|
- // dataName=evaluationLocal.name,
|
|
|
- // messageType=Constant._Message_type_message,
|
|
|
- // status=Constant._Message_status_warning,
|
|
|
- // content=$"检查到评测作答页面需要更新。[{webviewSize}]"
|
|
|
- // });
|
|
|
- //}
|
|
|
+
|
|
|
if (groupList==1)
|
|
|
{
|
|
|
await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
@@ -704,8 +750,9 @@ namespace IES.ExamServer.Controllers
|
|
|
});
|
|
|
return Ok(new
|
|
|
{
|
|
|
+ finalStatus,
|
|
|
code = 200,
|
|
|
- evaluation = evaluationLocal,
|
|
|
+ //evaluation = evaluationLocal,
|
|
|
data,
|
|
|
blob,
|
|
|
// webview,
|