csznet/tgState

提几个建议

Opened this issue · 2 comments

一是没有favicon,强迫症受不了。
二是检查一下为何经常出现上传失败,而且毫无规律
三是建议加上图片压缩功能,用户可选

因为对于vercel用户最大上传5mb,所以加入上传压缩功能

package control

import (
"encoding/json"
"html/template"
"image"
"image/jpeg"
"io"
"log"
"net/http"
"path/filepath"
"strconv"
"strings"

"golang.org/x/image/bmp"
"golang.org/x/image/tiff"

"csz.net/tgstate/assets"
"csz.net/tgstate/conf"
"csz.net/tgstate/utils"

)

// UploadImageAPI 上传图片api
func UploadImageAPI(w http.ResponseWriter, r http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "
")
if r.Method == http.MethodPost {
// 获取上传的文件
file, header, err := r.FormFile("image")
if err != nil {
errJsonMsg("Unable to get file", w)
return
}
defer file.Close()

	// 检查文件大小
	fileInfo, err := file.Stat()
	if err != nil {
		errJsonMsg("Error getting file info", w)
		return
	}
	if fileInfo.Size() > 5*1024*1024 {
		errJsonMsg("File size exceeds 5MB limit", w)
		return
	}

	// 检查文件类型
	allowedExts := []string{".jpg", ".jpeg", ".png", ".bmp", ".tiff"}
	ext := strings.ToLower(filepath.Ext(header.Filename))
	valid := false
	for _, allowedExt := range allowedExts {
		if ext == allowedExt {
			valid = true
			break
		}
	}
	if !valid {
		errJsonMsg("Invalid file type. Only .jpg, .jpeg, .png, .bmp, .tiff are allowed.", w)
		return
	}

	// 读取文件内容
	imgData, err := io.ReadAll(file)
	if err != nil {
		errJsonMsg("Error reading file data", w)
		return
	}

	// 压缩图像
	img, _, err := image.Decode(bytes.NewReader(imgData))
	if err != nil {
		errJsonMsg("Error decoding image", w)
		return
	}

	// 将图像压缩到5MB以下
	buf := new(bytes.Buffer)
	if ext == ".jpg" || ext == ".jpeg" {
		err = jpeg.Encode(buf, img, &jpeg.Options{Quality: 75})
	} else if ext == ".png" {
		// PNG压缩较为复杂,这里简单示例
		err = png.Encode(buf, img)
	} else if ext == ".bmp" {
		err = bmp.Encode(buf, img)
	} else if ext == ".tiff" {
		err = tiff.Encode(buf, img, nil)
	}
	if err != nil {
		errJsonMsg("Error encoding image", w)
		return
	}

	// 检查压缩后的文件大小
	if buf.Len() > 5*1024*1024 {
		errJsonMsg("Compressed file size exceeds 5MB limit", w)
		return
	}

	// 保存压缩后的图像
	imgData = buf.Bytes()

	res := conf.UploadResponse{
		Code:    0,
		Message: "error",
	}
	img := conf.FileRoute + utils.UpDocument(utils.TgFileData(header.Filename, bytes.NewReader(imgData)))
	if img != conf.FileRoute {
		res = conf.UploadResponse{
			Code:    1,
			Message: img,
			ImgUrl:  strings.TrimSuffix(conf.BaseUrl, "/") + img,
		}
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(res)
	return
}

// 如果不是POST请求,返回错误响应
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)

}

func errJsonMsg(msg string, w http.ResponseWriter) {
// 这里示例直接返回JSON响应
response := conf.UploadResponse{
Code: 0,
Message: msg,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}