ZBLOG

gorm.io/driver/mysql Upload

在使用 GORM 的 MySQL 驱动 (gorm.io/driver/mysql) 时,如果需要实现文件上传功能(例如将文件内容存储到数据库的 BLOB/LONGBLOB 字段),以下是完整的实现步骤和注意事项:


1. 准备数据库表

确保表中包含二进制字段(如 BLOBLONGBLOB):

CREATE TABLE `files` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(255) NOT NULL,
  `data` LONGBLOB,       -- 存储文件内容
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

对应 Go 结构体:

type File struct {
    ID        uint   `gorm:"primaryKey"`
    Name      string 
    Data      []byte // ← BLOB/LONGBLOB 字段
    CreatedAt time.Time
}

2. 实现文件上传

(1) HTTP API 示例(Gin + GORM)

package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
)

func UploadFile(c *gin.Context) {
    db := c.MustGet("db").(*gorm.DB)
    
    // 1.获取上传的文件
    file, err := c.FormFile("file") // <input type="file" name="file">
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    //2.读取文件内容到 []byte
    uploadedFile, err := file.Open()
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取文件"})
        return
    }
    defer uploadedFile.Close()

    fileData := make([]byte, file.Size)
	_, err = uploadedFile.Read(fileData)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "文件读取失败"})
		return
	}

	//3.保存到数据库
	newFile := File{
		Name: file.Filename,
		Data: fileData,
	}

	result := db.Create(&newFile)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
	    "message":   "上传成功",
	    "file_id":   newFile.ID,
	    "file_name": newFile.Name,
	    "size":      len(newFile.Data),
	})
}

(2) CURL测试上传

curl -X POST http://localhost:8080/upload \
     -F "file=@/path/to/your/file.jpg" \
     -H "Content-Type: multipart/form-data"

3.下载文件的实现

func DownloadFile(c *gin.Context) {
	db := c.MustGet("db").(*gorm.DB)
	id := c.Param("id")

	var file File
	
	if err := db.First(&file, id).Error; err != nil {
	    if errors.Is(err, gorm.ErrRecordNotFound) {
	        c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"})
	        return  
	    }
	    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) 
	    return  
	}  

	
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", file.Name))
	c.Data(http.StatusOK,"application/octet-stream", file.Data)
}

访问方式:

GET /download/:id  

4.关键注意事项

(1)性能优化

  • 大文件处理:对于超大文件(如 >100MB),建议直接存储到对象存储(如 S3/MinIO),数据库中只存路径。
  • 事务控制:大文件插入时启用事务避免内存溢出:
err = db.Transaction(func(tx *gorm.DB) error { 
	return tx.Create(&largeFile).Error 
}) 

(2)MySQL配置

  • 调整max_allowed_packet:确保 MySQL允许足够大的数据包:
SET GLOBAL max_allowed_packet=1073741824; --1GB 

在 my.cnf中永久生效:

[mysqld] 
max_allowed_packet=1G  

(3)替代方案

如果频繁操作二进制数据,推荐以下组合:

场景 推荐方案
小文件(<10MB) 直接存BLOB
大文件 对象存储+数据库存路径

如果有其他具体需求(如分片上传、进度监控等),可以进一步讨论!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23934

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?