我是靠谱客的博主 名字长了才好记,最近开发中收集的这篇文章主要介绍golang使用gin框架实现上传和水印增加常见图片类型限制,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 引入必要的依赖

确保在项目中引入了以下依赖,用于处理 GIF 格式的图片:

go get golang.org/x/image

2. 定义支持的图片类型

首先,我们定义一个支持的图片类型列表,便于在上传和处理过程中进行验证。

var supportedImageTypes = map[string]bool{    
"image/jpeg": true,    
"image/png":  true,    
"image/gif":  true,
}

3. 更新 uploadAndWatermark 函数

在上传处理函数中,我们增加对上传文件类型的验证,只有当文件类型在支持列表中时,才进行后续处理。

func uploadAndWatermark(c *gin.Context) {
    file, err := c.FormFile("file")
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "未收到文件"})
        return
    }

    // 打开上传的文件以读取其内容
    src, err := file.Open()
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取上传的文件"})
        return
    }
    defer src.Close()

    // 检查文件的实际 MIME 类型
    buf := make([]byte, 512)
    if _, err := src.Read(buf); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取文件内容"})
        return
    }
    fileType := http.DetectContentType(buf)

    // 重置文件指针
    if _, err := src.Seek(0, 0); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法重置文件指针"})
        return
    }

    // 验证文件类型
    if !supportedImageTypes[fileType] {
        c.JSON(http.StatusBadRequest, gin.H{"error": "不支持的文件类型"})
        return
    }

    // 保存上传的文件
    filename := filepath.Base(file.Filename)
    uploadPath := "./uploads/" + filename
    out, err := os.Create(uploadPath)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法保存上传的文件"})
        return
    }
    defer out.Close()

    if _, err = io.Copy(out, src); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法保存上传的文件内容"})
        return
    }

    // 添加水印
    watermarkedPath := "./uploads/watermarked_" + filename
    if err := addWatermark(uploadPath, "./watermark.png", watermarkedPath); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "无法添加水印", "details": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{
        "message": "文件上传并添加水印成功",
        "file":    watermarkedPath,
    })
}

解释

  • 文件类型检测:通过读取文件的前 512 个字节,使用 http.DetectContentType 函数检测实际的 MIME 类型,防止仅通过扩展名判断导致的安全问题。

  • 类型验证:将检测到的文件类型与支持的类型列表进行比对,只有匹配的类型才继续处理。

  • 文件保存:将上传的文件保存到指定目录。

  • 错误处理:在每个可能出错的地方添加错误处理,返回相应的错误信息。

4. 更新 addWatermark 函数

在添加水印的函数中,增加对水印图片类型的检测,并确保源图片和水印图片都在支持的类型范围内。

func addWatermark(srcPath, watermarkPath, destPath string) error {
    // 处理源图像
    srcImg, srcFormat, err := loadImage(srcPath)
    if err != nil {
        return fmt.Errorf("加载源图像失败: %v", err)
    }

    // 处理水印图像
    watermarkImg, watermarkFormat, err := loadImage(watermarkPath)
    if err != nil {
        return fmt.Errorf("加载水印图像失败: %v", err)
    }

    // 检查水印图片类型
    if !supportedImageTypes["image/"+watermarkFormat] {
        return fmt.Errorf("不支持的水印图像类型: %s", watermarkFormat)
    }

    // 计算水印位置(右下角)
    offset := image.Pt(
        srcImg.Bounds().Dx()-watermarkImg.Bounds().Dx()-10,
        srcImg.Bounds().Dy()-watermarkImg.Bounds().Dy()-10,
    )

    // 创建新的图像并合并水印
    b := srcImg.Bounds()
    m := image.NewRGBA(b)
    draw.Draw(m, b, srcImg, image.Point{}, draw.Src)
    draw.Draw(m, watermarkImg.Bounds().Add(offset), watermarkImg, image.Point{}, draw.Over)

    // 保存最终图像
    outFile, err := os.Create(destPath)
    if err != nil {
        return fmt.Errorf("创建输出文件失败: %v", err)
    }
    defer outFile.Close()

    switch srcFormat {
    case "jpeg":
        err = jpeg.Encode(outFile, m, &jpeg.Options{Quality: 90})
    case "png":
        err = png.Encode(outFile, m)
    case "gif":
        err = gif.Encode(outFile, m, nil)
    default:
        return fmt.Errorf("不支持的源图像格式: %s", srcFormat)
    }

    if err != nil {
        return fmt.Errorf("保存水印图像失败: %v", err)
    }

    return nil
}

辅助函数:loadImage

func loadImage(path string) (image.Image, string, error) {
    file, err := os.Open(path)    if err != nil {        return nil, "", err
    }    defer file.Close()

    img, format, err := image.Decode(file)    if err != nil {        return nil, "", err
    }    return img, format, nil}

解释

  • 加载图像:使用 loadImage 辅助函数统一加载源图像和水印图像,并获取其格式。

  • 类型验证:在加载水印图像后,验证其类型是否受支持。

  • 水印位置:将水印放置在源图像的右下角,距离边缘各 10 像素的位置。

  • 图像合并:使用 draw.Draw 将水印叠加到源图像上。

  • 图像保存:根据源图像的格式,选择合适的编码器保存最终图像。

  • 错误处理:在每个步骤中添加详细的错误信息,方便调试和错误追踪。


最后

以上就是名字长了才好记为你收集整理的golang使用gin框架实现上传和水印增加常见图片类型限制的全部内容,希望文章能够帮你解决golang使用gin框架实现上传和水印增加常见图片类型限制所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(339)

评论列表共有 0 条评论

立即
投稿
返回
顶部