c8f03dd932
功能特性: - Markdown 编辑与实时预览 - 代码语法高亮 - 目录树形结构管理 - 图片粘贴上传 - Markdown 文件导入导出 - 笔记密码保护 - 前后端分离架构 技术栈: - Go + Gin + GORM + SQLite - 原生 HTML/CSS/JavaScript - Highlight.js
90 rivejä
2.0 KiB
Go
90 rivejä
2.0 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// ImageHandler 图片上传处理器
|
|
type ImageHandler struct {
|
|
uploadDir string
|
|
}
|
|
|
|
// NewImageHandler 创建图片处理器
|
|
func NewImageHandler(uploadDir string) *ImageHandler {
|
|
return &ImageHandler{uploadDir: uploadDir}
|
|
}
|
|
|
|
// Init 初始化上传目录
|
|
func (h *ImageHandler) Init() error {
|
|
return os.MkdirAll(h.uploadDir, 0755)
|
|
}
|
|
|
|
// Upload 上传图片
|
|
func (h *ImageHandler) Upload(c *gin.Context) {
|
|
file, err := c.FormFile("image")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "请选择图片文件"})
|
|
return
|
|
}
|
|
|
|
// 验证文件类型
|
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
|
allowedExts := map[string]bool{
|
|
".jpg": true,
|
|
".jpeg": true,
|
|
".png": true,
|
|
".gif": true,
|
|
".webp": true,
|
|
".bmp": true,
|
|
}
|
|
|
|
if !allowedExts[ext] {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "不支持的图片格式,仅支持 jpg、png、gif、webp"})
|
|
return
|
|
}
|
|
|
|
// 验证文件大小 (最大 5MB)
|
|
if file.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "图片大小不能超过 5MB"})
|
|
return
|
|
}
|
|
|
|
// 生成唯一文件名
|
|
filename := fmt.Sprintf("%d_%s%s", time.Now().UnixNano(), randomString(8), ext)
|
|
filepath := filepath.Join(h.uploadDir, filename)
|
|
|
|
// 保存文件
|
|
if err := c.SaveUploadedFile(file, filepath); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "保存图片失败"})
|
|
return
|
|
}
|
|
|
|
// 返回访问 URL
|
|
url := "/uploads/" + filename
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"message": "上传成功",
|
|
"data": gin.H{
|
|
"url": url,
|
|
},
|
|
})
|
|
}
|
|
|
|
// randomString 生成随机字符串
|
|
func randomString(length int) string {
|
|
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
result := make([]byte, length)
|
|
for i := range result {
|
|
result[i] = chars[time.Now().UnixNano()%int64(len(chars))]
|
|
time.Sleep(time.Nanosecond)
|
|
}
|
|
return string(result)
|
|
}
|