csznet / tgState

使用Telegram作为存储的文件外链系统,不限制文件大小和格式。
https://www.csz.net
MIT License
874 stars 143 forks source link

提几个建议 #36

Open woshichenghaibo opened 3 weeks ago

woshichenghaibo commented 3 weeks ago

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

woshichenghaibo commented 2 weeks ago

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

woshichenghaibo commented 2 weeks ago

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