Skip to content

第30章:实战项目三 —— 文件分享服务 ​

本章目标 ​

使用 Gin 构建一个支持文件上传、分享链接、过期控制的文件分享服务

核心功能 ​

go
// 模型
type SharedFile struct {
	gorm.Model
	Filename    string    `json:"filename"`
	FilePath    string    `json:"-"`
	FileSize    int64     `json:"file_size"`
	ShareCode   string    `gorm:"uniqueIndex" json:"share_code"` // 6位分享码
	Password    string    `json:"-"`
	ExpireAt    time.Time `json:"expire_at"`
	DownloadCnt int       `gorm:"default:0" json:"download_count"`
	UserID      uint      `json:"user_id"`
}

// 上传文件
func Upload(c *gin.Context) {
	file, _ := c.FormFile("file")
	password := c.PostForm("password")
	expireHours, _ := strconv.Atoi(c.DefaultPostForm("expire_hours", "24"))

	// 保存文件
	dst := "./uploads/" + uuid.New().String() + "_" + file.Filename
	c.SaveUploadedFile(file, dst)

	// 创建分享记录
	share := SharedFile{
		Filename:  file.Filename,
		FilePath:  dst,
		FileSize:  file.Size,
		ShareCode: generateShareCode(),
		Password:  password,
		ExpireAt:  time.Now().Add(time.Duration(expireHours) * time.Hour),
		UserID:    c.GetUint("user_id"),
	}
	db.Create(&share)

	c.JSON(201, gin.H{"share_code": share.ShareCode, "expire_at": share.ExpireAt})
}

// 下载文件(验证密码和过期时间)
func Download(c *gin.Context) {
	code := c.Param("code")
	password := c.Query("password")

	var share SharedFile
	if db.Where("share_code = ?", code).First(&share).Error != nil {
		c.JSON(404, gin.H{"error": "分享码无效"})
		return
	}
	if time.Now().After(share.ExpireAt) {
		c.JSON(410, gin.H{"error": "链接已过期"})
		return
	}
	if share.Password != "" && share.Password != password {
		c.JSON(403, gin.H{"error": "密码错误"})
		return
	}

	db.Model(&share).UpdateColumn("download_count", gorm.Expr("download_count + 1"))
	c.FileAttachment(share.FilePath, share.Filename)
}

API 接口 ​

方法路径说明
POST/api/files/upload上传文件
GET/api/files我的文件列表
GET/api/files/:code文件信息
GET/dl/:code下载(分享链接)
DELETE/api/files/:code删除

限流配置 ​

go
// 分享下载限流:每个 IP 每分钟最多 10 次
dlGroup := r.Group("/dl")
dlGroup.Use(RateLimiter(10, time.Minute))
{
	dlGroup.GET("/:code", Download)
}

练习题 ​

  1. 实现完整的文件分享服务。
  2. 添加文件类型过滤(只允许图片/PDF)。
  3. 实现下载次数统计和排行榜。
  4. 添加文件预览功能(图片在线预览,其他文件显示信息)。

把零散知识,整理成可以反复走的路。