package webodm import ( "bytes" "context" "encoding/base64" "encoding/json" "errors" "fmt" "github.com/go-resty/resty/v2" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "github.com/tidwall/gjson" "github.com/tiger1103/gfast/v3/api/v1/common/coryCommon" "io" "io/ioutil" "mime/multipart" "net/http" "net/url" "os" fpath "path/filepath" "strconv" "strings" "time" ) // 获取项目列表及其对应的任务列表 func (w WebOdmApi) ProjectList(ctx context.Context, req *ProjectListReq) (res *ProjectListRes, err error) { res, err = ProjectListFunc() return } func ProjectListFunc() (res *ProjectListRes, err error) { res = new(ProjectListRes) url := fmt.Sprintf("http://%s:%s/api/projects/?ordering=-created_at&page=1", Host, Port) // 创建基本身份验证信息 auth := Username + ":" + Password authEncoded := base64.StdEncoding.EncodeToString([]byte(auth)) // 创建请求 request, err := http.NewRequest("GET", url, nil) if err != nil { fmt.Println("Error creating request:", err) return nil, err } // 添加基本身份验证信息到请求头 request.Header.Set("Authorization", "Basic "+authEncoded) // 发送请求 client := &http.Client{} resp, err := client.Do(request) if err != nil { fmt.Println("Error sending request:", err) return nil, err } defer resp.Body.Close() // 读取响应体 body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return nil, err } // 解析 JSON 响应 var projectsResponse ProjectsResponse err = json.Unmarshal(body, &projectsResponse) if err != nil { fmt.Println("Error decoding JSON:", err) return nil, err } // 设置响应结果 res.ProjectsResponse = projectsResponse return res, nil } // 创建任务 func (w WebOdmApi) TaskCreate(ctx context.Context, req *TaskCreateReq) (res *TaskCreateRes, err error) { res = new(TaskCreateRes) res, err = TaskCreateFunc(ctx, req) return } func TaskCreateFunc(ctx context.Context, req *TaskCreateReq) (res *TaskCreateRes, err error) { res = new(TaskCreateRes) // 准备图片 URL 列表 imageURLs := req.UrlList // 准备一个 buffer 来保存 multipart form 的内容 body := &bytes.Buffer{} writer := multipart.NewWriter(body) // 遍历图片 URL 列表并从 URL 获取图片并添加到 multipart form 中 for i, imageURL := range imageURLs { // 从 URL 获取图片 resp, err := http.Get(imageURL) if err != nil { fmt.Println("Failed to fetch image from URL:", err) return res, err } defer resp.Body.Close() // 准备一个 multipart form 的 part,将图片数据写入 part, err := writer.CreateFormFile("file"+strconv.Itoa(i+1), fpath.Base(imageURL)) if err != nil { fmt.Println("Failed to create form file:", err) return res, err } _, err = io.Copy(part, resp.Body) if err != nil { fmt.Println("Failed to write image data:", err) return res, err } } // 写入项目ID到 multipart form 中 writer.WriteField("project_id", req.ProjectId) // 设置任务参数,以生成合并后的tif图片 writer.WriteField("merge", "true") // 关闭 multipart writer writer.Close() // 创建包含基本身份验证的请求 url := fmt.Sprintf("http://%s:%s/api/projects/%s/tasks/", Host, Port, req.ProjectId) request, err := http.NewRequest("POST", url, body) if err != nil { fmt.Println("Failed to create request:", err) return res, err } // 添加基本身份验证信息 auth := Username + ":" + Password authEncoded := base64.StdEncoding.EncodeToString([]byte(auth)) request.Header.Set("Authorization", "Basic "+authEncoded) // 设置请求头中的 Content-Type 为 multipart/form-data request.Header.Set("Content-Type", writer.FormDataContentType()) // 发送请求 client := &http.Client{} resp, err := client.Do(request) if err != nil { fmt.Println("Failed to send request:", err) return res, err } defer resp.Body.Close() // 读取响应体 respBody, err := io.ReadAll(resp.Body) if err != nil { fmt.Println("Failed to read response body:", err) return res, err } // 解析 JSON 响应 var jsonResponse map[string]interface{} err = json.Unmarshal(respBody, &jsonResponse) if err != nil { fmt.Println("Failed to parse JSON response:", err) return res, err } // 提取任务ID taskID, ok := jsonResponse["id"].(string) if !ok { fmt.Println("Failed to extract task ID from response") return res, err } // 设置任务ID到响应结构体中 res.TaskId = taskID return res, nil } // 获取任务进度 func (w WebOdmApi) TaskProcess(ctx context.Context, req *TaskProcessReq) (*TaskProcessRes, error) { ressss, err := TaskProcessFunc(ctx, req) return ressss, err } func TaskProcessFunc(ctx context.Context, req *TaskProcessReq) (res *TaskProcessRes, err error) { res = new(TaskProcessRes) // 构建请求 URL url := fmt.Sprintf("http://%s:%s/api/projects/"+req.ProjectId+"/tasks/%s/", Host, Port, req.TaskId) // 创建基本身份验证信息 auth := Username + ":" + Password authEncoded := base64.StdEncoding.EncodeToString([]byte(auth)) // 创建请求 request, err := http.NewRequest("GET", url, nil) if err != nil { fmt.Println("Error creating request:", err) return nil, err } // 添加基本身份验证信息到请求头 request.Header.Set("Authorization", "Basic "+authEncoded) // 发送请求 client := &http.Client{} resp, err := client.Do(request) if err != nil { fmt.Println("Error sending request:", err) return nil, err } defer resp.Body.Close() // 读取响应体 body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return nil, err } // 解析 JSON 响应 err = json.Unmarshal(body, res) if err != nil { fmt.Println("Error decoding JSON:", err) return nil, err } return res, nil } // 下载任务得到的结果 func (w WebOdmApi) DownloadTask(ctx context.Context, req *TaskDownloadReq) (res *TaskDownloadRes, err error) { res, err = DownloadTask(ctx, req) return } func DownloadTask(ctx context.Context, req *TaskDownloadReq) (res *TaskDownloadRes, err error) { res = new(TaskDownloadRes) // 构建请求 URL requestURL := fmt.Sprintf("http://%s:%s/api/projects/"+req.ProjectId+"/tasks/%s/orthophoto/export", Host, Port, req.TaskId) // 创建基本身份验证信息 auth := Username + ":" + Password authEncoded := base64.StdEncoding.EncodeToString([]byte(auth)) // 获取任务的 epsg epsg, err := GetEpsgByTaskID(req.ProjectId, req.TaskId) if err != nil { return nil, err } // 构建请求体 form := url.Values{} form.Set("format", req.Format) form.Set("epsg", epsg) // 创建请求 httpRequest, err := http.NewRequest("POST", requestURL, strings.NewReader(form.Encode())) if err != nil { return nil, err } // 设置基本身份验证头部 httpRequest.Header.Set("Authorization", "Basic "+authEncoded) httpRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") // 执行请求 client := &http.Client{} httpResponse, err := client.Do(httpRequest) if err != nil { return nil, err } defer httpResponse.Body.Close() // 读取响应体 responseBody, err := ioutil.ReadAll(httpResponse.Body) if err != nil { return nil, err } var TaskExportRes struct { CeleryTaskID string `json:"celery_task_id"` Filename string `json:"filename"` } // 解析 JSON 响应 err = json.Unmarshal(responseBody, &TaskExportRes) if err != nil { return nil, err } celeryTaskID := TaskExportRes.CeleryTaskID filename := TaskExportRes.Filename type WorkerCheckRes struct { Ready bool `json:"ready"` } // 定义 worker 检查结果的变量 var workerCheckRes WorkerCheckRes // 循环检查任务状态,直到 Ready 为 true for { // 发起请求到 http://%s:%s/api/workers/check/celeryTaskID workerCheckURL := fmt.Sprintf("http://%s:%s/api/workers/check/%s", Host, Port, celeryTaskID) // 创建新的 GET 请求 workerCheckRequest, err := http.NewRequest("GET", workerCheckURL, nil) if err != nil { return nil, err } // 设置基本身份验证头部 workerCheckRequest.Header.Set("Authorization", "Basic "+authEncoded) workerCheckRequest.Header.Set("Accept", "application/json") // 执行 GET 请求 workerCheckResponse, err := client.Do(workerCheckRequest) if err != nil { return nil, err } defer workerCheckResponse.Body.Close() // 读取 GET 响应体 workerCheckResponseBody, err := ioutil.ReadAll(workerCheckResponse.Body) if err != nil { return nil, err } // 解析 GET 响应 err = json.Unmarshal(workerCheckResponseBody, &workerCheckRes) if err != nil { return nil, err } // 输出 worker 检查结果 fmt.Println("Worker Check Result:", workerCheckRes) // 如果 Ready 为 true,则退出循环 if workerCheckRes.Ready { break } // 如果 Ready 为 false,则等待 1 秒后重新检查 time.Sleep(1 * time.Second) } // 构建下载 URL downloadURL := fmt.Sprintf("http://%s:%s/api/workers/get/%s?filename=%s", Host, Port, celeryTaskID, filename) // 发送 GET 请求并获取响应 resp, err := http.Get(downloadURL) if err != nil { return nil, err } defer resp.Body.Close() // 检查响应状态码 if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) } // 读取图片数据 imageData, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } // 创建目标文件夹路径 if err := os.MkdirAll(coryCommon.UavMerge, os.ModePerm); err != nil { return nil, err } // 构建文件名,添加当前时间的年月日时分秒作为前缀 currentTime := time.Now().Format("20060102150405") fileNameWithTime := fmt.Sprintf("%s%s", currentTime, filename) // 构建文件路径 filepath := fpath.Join(coryCommon.UavMerge, fileNameWithTime) // 写入图片数据到文件 err = ioutil.WriteFile(filepath, imageData, 0644) if err != nil { return nil, err } // 打印下载文件的信息 fmt.Printf("Downloaded image saved as: %s\n", filepath) // 获取IP和端口 //host := g.RequestFromCtx(ctx).Host res.FileUrl = fmt.Sprintf("/%s/%s", coryCommon.UavMerge, fileNameWithTime) return res, nil } // GetEpsgByTaskID 根据任务ID 获取 epsg func GetEpsgByTaskID(projectID, taskID string) (string, error) { client := &http.Client{} auth := Username + ":" + Password authEncoded := base64.StdEncoding.EncodeToString([]byte(auth)) url := fmt.Sprintf("http://%s:%s/api/projects/%s/tasks/?ordering=-created_at", Host, Port, projectID) request, err := http.NewRequest("GET", url, nil) if err != nil { return "", err } request.Header.Set("Authorization", "Basic "+authEncoded) resp, err := client.Do(request) if err != nil { return "", err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", err } result := gjson.Parse(string(body)) for _, value := range result.Array() { if value.Get("id").String() == taskID { return value.Get("epsg").String(), nil } } return "", nil } // @Title DelUuidFunc 2024/8/13 11:40:00 // @Description 根据项目ID及任务ID 找到资源并删除 // @Auth Cory // @param projectID ---> "webdom项目ID" // @Return taskID ---> "webdom任务ID" func DelUuidFunc(projectID, taskID string) (flag bool, err error) { client := resty.New() header := client.R(). SetHeader("Content-Type", "application/json"). SetHeader("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(Username+":"+Password))) //1、获取uuid url := fmt.Sprintf("http://%s:%s/api/projects/%s/tasks/%s", Host, Port, projectID, taskID) resp, err := header.Get(url) if err != nil { g.Log().Error(gctx.New(), err) return } uuid := gjson.Get(string(resp.Body()), "uuid").String() if uuid == "" { err = errors.New("删除失败,无法获取uuid!") return } //2、根据uuid去删除对应的资源 m := make(map[string]string) m["uuid"] = uuid url = url + "/remove/" post, err := header.SetBody(m).Post(url) if err != nil { g.Log().Error(gctx.New(), err) return false, err } return gjson.Get(string(post.Body()), "succeed").Bool(), nil }