362 lines
9.0 KiB
Go
362 lines
9.0 KiB
Go
|
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("\\<style[\\S\\s]+?\\</style\\>")
|
|||
|
src = re.ReplaceAllString(src, "")
|
|||
|
//去除SCRIPT
|
|||
|
re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
|
|||
|
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
|
|||
|
}
|