Files
zmkgC/api/v1/common/coryCommon/imgData.go
2025-07-07 20:11:59 +08:00

210 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}