tencent_ocr/pkg/handler/upload.go
2025-01-15 14:15:52 +08:00

130 lines
3.5 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.

// 上传文件到cloudflare R2
package handler
import (
"bytes"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
type UploadHandler struct {
accessKey string
secretKey string
bucket string
endpoint string
customDomain string
}
type UploadRequest struct {
File string `json:"file" binding:"required"`
APIKey string `json:"apikey" binding:"required"`
}
type UploadResponse struct {
ImageURL string `json:"image_url"`
Success bool `json:"success"`
}
func NewUploadHandler(accessKey, secretKey, bucket, endpoint, customDomain string) *UploadHandler {
return &UploadHandler{
accessKey: accessKey,
secretKey: secretKey,
bucket: bucket,
endpoint: endpoint,
customDomain: customDomain,
}
}
// 上传文件到cloudflare R2。判断文件是否是图片如果是图片则上传到R2并返回图片的url如果不是图片则返回错误。
// 图片大小限制为10M图片格式为jpg, jpeg, png, gif, bmp, tiff, webp
// HandleUpload 上传文件到Cloudflare R2
func (h *UploadHandler) HandleUpload(c *gin.Context) {
// 解析请求体
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to read file from request"})
return
}
defer file.Close()
// 读取文件内容
fileBuffer := make([]byte, header.Size)
_, err = file.Read(fileBuffer)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read file content"})
return
}
// 验证文件类型
contentType := http.DetectContentType(fileBuffer)
if !isImage(contentType) {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid file type. Only images are allowed"})
return
}
// 验证文件大小
if header.Size > 10<<20 { // 10MB
c.JSON(http.StatusBadRequest, gin.H{"error": "File size exceeds the limit of 10MB"})
return
}
// 上传文件到R2
imageURL, err := h.uploadToR2(fileBuffer, header.Filename, contentType)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to upload file to R2: %v", err)})
return
}
// 返回结果
response := UploadResponse{
ImageURL: imageURL,
Success: true,
}
c.JSON(http.StatusOK, response)
}
// uploadToR2 上传文件到Cloudflare R2
func (h *UploadHandler) uploadToR2(file []byte, fileName, contentType string) (string, error) {
// 创建S3会话
sess, err := session.NewSession(&aws.Config{
Endpoint: aws.String(h.endpoint),
Region: aws.String("auto"),
Credentials: credentials.NewStaticCredentials(h.accessKey, h.secretKey, ""),
})
if err != nil {
return "", fmt.Errorf("failed to create S3 session: %v", err)
}
// 创建S3服务客户端
svc := s3.New(sess)
// 上传文件到R2
_, err = svc.PutObject(&s3.PutObjectInput{
Bucket: aws.String(h.bucket),
Key: aws.String(fileName),
Body: bytes.NewReader(file),
ContentType: aws.String(contentType),
ACL: aws.String("public-read"), // 设置文件为公开可读
})
if err != nil {
return "", fmt.Errorf("failed to upload file to R2: %v", err)
}
// 生成文件的URL
imageURL := fmt.Sprintf("https://%s/%s", h.customDomain, fileName)
return imageURL, nil
}
// isImage 检查文件是否是图片
func isImage(contentType string) bool {
allowedTypes := []string{"image/jpeg", "image/png", "image/gif", "image/bmp", "image/tiff", "image/webp"}
for _, t := range allowedTypes {
if contentType == t {
return true
}
}
return false
}