diff --git a/Common/Output.go b/Common/Output.go index f5cf206..0d6c97c 100644 --- a/Common/Output.go +++ b/Common/Output.go @@ -70,6 +70,13 @@ func InitOutput() error { if ApiAddr != "" { OutputFormat = "csv" Outputfile = filepath.Join(dir, "fscanapi.csv") + Num = 0 + End = 0 + if _, err := os.Stat(Outputfile); err == nil { + if err := os.Remove(Outputfile); err != nil { + return fmt.Errorf(GetText("output_file_remove_failed", err)) + } + } } manager := &OutputManager{ diff --git a/RPC/lib/rpc.pb.go b/RPC/lib/rpc.pb.go index d692b0d..dd902de 100644 --- a/RPC/lib/rpc.pb.go +++ b/RPC/lib/rpc.pb.go @@ -232,6 +232,8 @@ type TaskResultsResponse struct { TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` Results []*ScanResult `protobuf:"bytes,2,rep,name=results,proto3" json:"results,omitempty"` Finished bool `protobuf:"varint,3,opt,name=finished,proto3" json:"finished,omitempty"` + Total int64 `protobuf:"varint,4,opt,name=total,proto3" json:"total,omitempty"` // 总结果数 + End int64 `protobuf:"varint,5,opt,name=end,proto3" json:"end,omitempty"` // 结束结果数 unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -287,6 +289,20 @@ func (x *TaskResultsResponse) GetFinished() bool { return false } +func (x *TaskResultsResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *TaskResultsResponse) GetEnd() int64 { + if x != nil { + return x.End + } + return 0 +} + // 扫描结果结构体 type ScanResult struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -380,11 +396,13 @@ const file_lib_rpc_proto_rawDesc = "" + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12\x1d\n" + "\n" + "Start_time\x18\x02 \x01(\tR\tStartTime\x12\x19\n" + - "\bEnd_time\x18\x03 \x01(\tR\aEndTime\"u\n" + + "\bEnd_time\x18\x03 \x01(\tR\aEndTime\"\x9d\x01\n" + "\x13TaskResultsResponse\x12\x17\n" + "\atask_id\x18\x01 \x01(\tR\x06taskId\x12)\n" + "\aresults\x18\x02 \x03(\v2\x0f.lib.ScanResultR\aresults\x12\x1a\n" + - "\bfinished\x18\x03 \x01(\bR\bfinished\"\xa0\x01\n" + + "\bfinished\x18\x03 \x01(\bR\bfinished\x12\x14\n" + + "\x05total\x18\x04 \x01(\x03R\x05total\x12\x10\n" + + "\x03end\x18\x05 \x01(\x03R\x03end\"\xa0\x01\n" + "\n" + "ScanResult\x12\x12\n" + "\x04time\x18\x01 \x01(\tR\x04time\x12\x12\n" + diff --git a/RPC/lib/rpc.proto b/RPC/lib/rpc.proto index 92cb44a..bcde5d2 100644 --- a/RPC/lib/rpc.proto +++ b/RPC/lib/rpc.proto @@ -59,6 +59,8 @@ message TaskResultsResponse { string task_id = 1; repeated ScanResult results = 2; bool finished = 3; + int64 total = 4; // 总结果数 + int64 end = 5; // 结束结果数 } // 扫描结果结构体 diff --git a/RPC/service/fscan.go b/RPC/service/fscan.go index 935e05d..62f7960 100644 --- a/RPC/service/fscan.go +++ b/RPC/service/fscan.go @@ -66,21 +66,30 @@ func (s *FscanService) StartScan(ctx context.Context, req *pb.StartScanRequest) } func (s *FscanService) GetScanResults(ctx context.Context, req *pb.TaskResultsRequest) (*pb.TaskResultsResponse, error) { + // 获取扫描结果 results, err := Common.GetResults() if err != nil { + // 记录详细错误信息 + Common.LogError(fmt.Sprintf("读取结果失败: %v", err)) return nil, fmt.Errorf("读取结果失败: %w", err) } + // 创建一个用于存储转换后的pb扫描结果的切片 pbResults := make([]*pb.ScanResult, 0, len(results)) + + // 遍历每一项结果,进行转换 for _, r := range results { + // 尝试将详情转换为Struct detailsStruct, err := structpb.NewStruct(r.Details) if err != nil { - Common.LogError(fmt.Sprintf("转换为 Struct 失败: %v", err)) + // 记录转换失败的详细信息,并跳过当前项 + Common.LogError(fmt.Sprintf("转换为 Struct 失败 (Target: %s, Type: %s): %v", r.Target, r.Type, err)) continue } + // 将转换后的结果添加到 pbResults pbResults = append(pbResults, &pb.ScanResult{ - Time: r.Time.Format(time.RFC3339), + Time: r.Time.Format(time.RFC3339), // 使用 RFC3339 格式化时间 Type: string(r.Type), Target: r.Target, Status: r.Status, @@ -88,10 +97,21 @@ func (s *FscanService) GetScanResults(ctx context.Context, req *pb.TaskResultsRe }) } + // 通过原子操作判断扫描是否完成 finished := atomic.LoadInt32(&s.isScanning) == 0 + + // 如果任务未完成,计算 Total 和 End,仅在需要时计算 + var total, end int64 + if !finished { + total = Common.Num + end = Common.End + } + + // 返回响应 return &pb.TaskResultsResponse{ - TaskId: req.Filter.TaskId, Results: pbResults, Finished: finished, + Total: total, // 返回 Total + End: end, // 返回 End }, nil }