package service import ( "bytes" "encoding/json" "errors" "fmt" "io" "io/ioutil" "math/rand" "net/http" "os" "os/exec" "path/filepath" "regexp" "strconv" "strings" "time" ) // PostJSON 发送HTTP POST请求并发送JSON数据 func PostJSON(url string, jsonData interface{}) ([]byte, error) { // 将JSON数据转换为字节切片 jsonBytes, err := json.Marshal(jsonData) if err != nil { return nil, err } // 创建一个HTTP请求 req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") // 发送HTTP请求并获取响应 client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() // 读取响应的内容 respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } return respBody, nil } /* * 去除html标签,过滤html标签 */ func TrimHtml(src string) string { //将HTML标签全转换成小写 re, _ := regexp.Compile("\\<[\\S\\s]+?\\>") src = re.ReplaceAllStringFunc(src, strings.ToLower) //去除STYLE re, _ = regexp.Compile("\\") src = re.ReplaceAllString(src, "") //去除SCRIPT re, _ = regexp.Compile("\\") src = re.ReplaceAllString(src, "") //去除所有尖括号内的HTML代码,并换成换行符 re, _ = regexp.Compile("\\<[\\S\\s]+?\\>") src = re.ReplaceAllString(src, "\n") //去除连续的换行符 re, _ = regexp.Compile("\\s{2,}") src = re.ReplaceAllString(src, "\n") return strings.TrimSpace(src) } // GetIDCardFromText 从文本中提取身份证号 func GetIDCardFromText(str string) (string, error) { // 正则表达式,匹配18位或15位的身份证号 // 18位身份证号格式: XXXXXXYYYYMMDDXXXXXX // 15位身份证号格式: XXXXXXYYYYMMDDXXX // 其中X表示数字 var idCardRegex = regexp.MustCompile(`\d{17}[\dXx]|\d{15}`) matches := idCardRegex.FindAllString(str, -1) if len(matches) == 0 { return "", errors.New("没有找到身份证号") } // 如果有多个身份证号,返回第一个找到的 // 或者根据具体需求可以返回所有匹配的身份证号 return matches[0], nil } // 根据输入的字符串参数决定返回的随机数。如果参数包含 -,则将其解析为范围,并返回该范围内的随机整数。如果参数不包含 -,则将其解析为整数并直接返回 func GetRandomValue(input string) (int, error) { if strings.Contains(input, "-") { ranges := strings.Split(input, "-") if len(ranges) != 2 { return 0, fmt.Errorf("invalid input format") } min, err := strconv.Atoi(ranges[0]) if err != nil { return 0, fmt.Errorf("invalid minimum value") } max, err := strconv.Atoi(ranges[1]) if err != nil { return 0, fmt.Errorf("invalid maximum value") } if min >= max { return 0, fmt.Errorf("minimum value must be less than maximum value") } return rand.Intn(max-min+1) + min, nil } else { val, err := strconv.Atoi(input) if err != nil { return 0, fmt.Errorf("invalid integer value") } return val, nil } } // isWindowsPath 判断字符串是否是有效的Windows文件路径 func IsWindowsPath(path string) bool { // 检查路径是否以驱动器号开头,如 "C:\" if len(path) > 2 && path[1] == ':' && path[2] == filepath.Separator { // 检查路径中是否包含反斜杠 for i := 3; i < len(path); i++ { if path[i] == filepath.Separator { return true } } } return false } // isImagePath 判断字符串是否可能是一个图片路径 func IsImagePath(path string) bool { // 定义常见的图片文件扩展名 imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".bmp"} // 获取路径的文件名部分 fileName := filepath.Base(path) // 检查文件名是否以这些扩展名之一结尾 for _, ext := range imageExtensions { if strings.ToLower(strings.TrimPrefix(fileName, ext)) == fileName { return true } } // 如果没有匹配的扩展名,则不是图片路径 return false } // 正则提取 func GetOneStringByRegex(str, rule string) (string, error) { reg, err := regexp.Compile(rule) if reg == nil || err != nil { return "", errors.New("正则MustCompile错误:" + err.Error()) } //提取关键信息 result := reg.FindStringSubmatch(str) if len(result) < 1 { return "", errors.New("没有获取到子字符串") } return result[1], nil } func ParseImgMessage(str string) string { var url string url, _ = GetOneStringByRegex(str, "img\\[(.*?)\\]") return url } // 下载一个网络文件并保存到本地 func DownloadFile(url string, filename string) error { // 创建一个HTTP客户端 client := &http.Client{} // 发送GET请求 req, err := http.NewRequest("GET", url, nil) if err != nil { return err } // 发送请求并获取响应 resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() // 检查HTTP响应状态码 if resp.StatusCode != http.StatusOK { return fmt.Errorf("服务器返回状态码: %d", resp.StatusCode) } // 创建文件并写入响应体内容 out, err := os.Create(filename) if err != nil { return err } defer out.Close() // 将响应体内容写入文件 _, err = io.Copy(out, resp.Body) if err != nil { return err } return nil } // 定义一个结构体来存储图片的路径和描述 type MarkdownImage struct { Path string Desc string } // 定义一个函数来提取Markdown中的图片路径和描述 func ExtractMarkdownImagePaths(markdown string) []MarkdownImage { // 正则表达式匹配Markdown图片路径和描述 // 组1: 图片描述,组2: 图片路径 re := regexp.MustCompile(`!\[(.*?)\]\((.*?)\)`) // 使用FindAllStringSubmatch查找所有匹配的图片路径和描述 matches := re.FindAllStringSubmatch(markdown, -1) // 初始化一个切片来存储MarkdownImage结构体 images := make([]MarkdownImage, len(matches)) // 提取图片路径和描述 for i, match := range matches { if len(match) < 3 { // 确保有足够的匹配组 continue } images[i] = MarkdownImage{ Path: match[2], // 索引2是图片路径 Desc: match[1], // 索引1是图片描述 } } return images } // 获取当前日期格式化为年月日的字符串 func GetCurrentDateDir() string { currentTime := time.Now() // 获取当前时间 // 格式化为年月日,例如 "20240624" dateStr := currentTime.Format("20060102") return dateStr } // 创建按照当前年月日命名的目录 func CreateDateDir(baseDir, dateStr string) error { dirPath := filepath.Join(baseDir, dateStr) // 构建目录路径 if _, err := os.Stat(dirPath); os.IsNotExist(err) { // 如果目录不存在,则创建目录 err := os.MkdirAll(dirPath, 0755) if err != nil { return err } } return nil } // 从URL中提取文件名和扩展名 func ExtractFilenameAndExt(url string) (string, string) { // 提取URL中的最后一个路径部分作为文件名 filename := filepath.Base(url) // 分割文件名和扩展名 ext := filepath.Ext(filename) // 如果没有扩展名,返回空字符串 if ext == filename { ext = "" } else { // 移除点号,只保留扩展名 ext = ext[1:] } return filename, ext } // 下载图片到按照当前年月日创建的目录 func DownloadImageToDailyDir(url, baseResourceDir, filename string) (string, error) { // 从URL中提取文件名和扩展名 fileNameWithoutExt, ext := ExtractFilenameAndExt(url) // 如果提供的filename为空,则使用从URL中提取的文件名 if filename == "" { filename = fileNameWithoutExt } // 如果文件名没有扩展名,则添加从URL中提取的扩展名 if !strings.Contains(filename, "."+ext) { filename += "." + ext } // 获取当前日期目录名 dateDir := GetCurrentDateDir() // 创建基础目录和日期目录 if err := CreateDateDir(baseResourceDir, dateDir); err != nil { return "", err } // 构建文件路径 filePath := filepath.Join(baseResourceDir, dateDir, filename) // 下载图片 resp, err := http.Get(url) if err != nil { return "", err } defer resp.Body.Close() // 检查响应状态码 if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("http status code: %d", resp.StatusCode) } // 创建文件并打开文件句柄 file, err := os.Create(filePath) if err != nil { return "", err } defer file.Close() // 将响应体的内容写入文件 _, err = io.Copy(file, resp.Body) if err != nil { return "", err } return filePath, nil } // 判断文件文件夹不存在 func IsFileNotExist(path string) (bool, error) { _, err := os.Stat(path) if os.IsNotExist(err) { return true, nil } return false, err } // 获取程序执行目录 func GetRunPath2() string { file, _ := exec.LookPath(os.Args[0]) path, _ := filepath.Abs(file) index := strings.LastIndex(path, string(os.PathSeparator)) ret := path[:index] return ret } // 获取程序根目录 func GetRootPath() string { rootPath, _ := os.Getwd() if notExist, _ := IsFileNotExist(rootPath); notExist { rootPath = GetRunPath2() if notExist, _ := IsFileNotExist(rootPath); notExist { rootPath = "." } } return rootPath }