210 lines
4.9 KiB
Go
210 lines
4.9 KiB
Go
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)
|
||
}
|