Files
zmkgC/api/v1/common/coryCommon/imgData.go

210 lines
4.9 KiB
Go
Raw Normal View History

2025-07-07 20:11:59 +08:00
package coryCommon
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"io/ioutil"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
)
const (
MinShortEdge = 15
MaxLongEdge = 4096
MaxSize = 1024 * 1024 // 4MB
SupportedExts = ".jpg .jpeg .png .bmp"
)
func ImgDataBase64(filePath string) (err error, encodedURL string) {
file, err := os.Open(filePath)
if err != nil {
fmt.Println("打开图像文件失败:", err)
err = errors.New("打开图像文件失败")
return
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
fmt.Println("读取图像文件信息失败:", err)
err = errors.New("读取图像文件信息失败")
return
}
fileSize := fileInfo.Size()
if fileSize > MaxSize {
fmt.Println("图像文件大小超过限制:", fileSize)
err = errors.New("图像文件大小超过限制")
return
}
imgData, err := ioutil.ReadAll(file)
if err != nil {
fmt.Println("读取图像文件内容失败:", err)
err = errors.New("读取图像文件内容失败")
return
}
bounds, format, err := image.DecodeConfig(bytes.NewReader(imgData))
if err != nil {
fmt.Println("解码图像配置失败:", err)
err = errors.New("解码图像配置失败")
return
}
if format != "jpeg" && format != "jpg" && format != "png" && format != "bmp" {
fmt.Println("不支持的图像格式:", format)
//err = errors.New("不支持的图像格式")
err = errors.New("支持的图像格式为jpg、png、gif、bmp")
return
}
width := bounds.Width
height := bounds.Height
shortEdge := width
if height < width {
shortEdge = height
}
if shortEdge < MinShortEdge {
fmt.Println("图像尺寸的最短边小于要求:", shortEdge)
str := "图像尺寸的最短边小于要求:" + strconv.Itoa(shortEdge)
err = errors.New(str)
return
}
if width > MaxLongEdge || height > MaxLongEdge {
fmt.Println("图像尺寸的最长边超过限制:", width, height)
str := "图像尺寸的最长边超过限制:" + strconv.Itoa(width) + strconv.Itoa(height)
err = errors.New(str)
return
}
// Base64编码图像数据
encodedStr := base64.StdEncoding.EncodeToString(imgData)
// URL编码
//urlEncodedStr := url.QueryEscape(encodedStr)
//fmt.Println("Base64编码并URL编码后的图像数据:", urlEncodedStr)
return err, encodedStr
}
/*
EncodeAndUrlEncodeImage 图片文件的绝对路径
功能
图像数据base64编码后进行urlencode需去掉编码头data:image/jpeg;base64, 要求base64编码和urlencode后大小不超过N兆最短边至少15px最长边最大4096px,支持jpg/jpeg/png/bmp格式
*/
func EncodeAndUrlEncodeImage(filePath string, size int64) (string, error) {
// 检查文件是否存在
_, err := os.Stat(filePath)
if os.IsNotExist(err) {
return "", fmt.Errorf("文件 %s 不存在", filePath)
}
// 检查文件大小
fileSize := getFileSize(filePath)
if fileSize > (size * MaxSize) {
return "", fmt.Errorf("文件大小超过限制")
}
// 检查图像尺寸
img, err := loadImage(filePath)
if err != nil {
return "", fmt.Errorf("无法加载图像: %s", err)
}
bounds := img.Bounds()
if !isValidSize(bounds) {
return "", fmt.Errorf("图像尺寸不符合要求")
}
// 读取文件
fileData, err := ioutil.ReadFile(filePath)
if err != nil {
return "", fmt.Errorf("无法读取文件: %s", err)
}
// 获取文件后缀名
ext := filepath.Ext(filePath)
// 检查是否支持的文件格式
if !isSupportedFormat(ext) {
return "", fmt.Errorf("不支持的文件格式")
}
// 将图像数据进行 base64 编码
encodedData := base64.StdEncoding.EncodeToString(fileData)
// 去掉编码头(如:"data:image/jpeg;base64,"
encodedData = removeEncodingHeader(encodedData, ext)
//// 对 base64 编码后的数据进行 URL 编码
//encodedData = urlEncode(encodedData)
return encodedData, nil
}
func getFileSize(filePath string) int64 {
fileInfo, err := os.Stat(filePath)
if err != nil {
return 0
}
return fileInfo.Size()
}
func loadImage(filePath string) (image.Image, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
img, _, err := image.Decode(file)
if err != nil {
return nil, err
}
return img, nil
}
func isValidSize(bounds image.Rectangle) bool {
width := bounds.Dx()
height := bounds.Dy()
if width < MinShortEdge || height < MinShortEdge {
return false
}
if width > MaxLongEdge || height > MaxLongEdge {
return false
}
return true
}
func isSupportedFormat(ext string) bool {
ext = strings.ToLower(ext)
return strings.Contains(SupportedExts, ext)
}
func removeEncodingHeader(encodedData string, ext string) string {
header := fmt.Sprintf("data:image/%s;base64,", ext[1:])
if strings.HasPrefix(encodedData, header) {
encodedData = strings.TrimPrefix(encodedData, header)
}
return encodedData
}
func urlEncode(data string) string {
return url.PathEscape(data)
}