概述
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框架实现上传和水印增加常见图片类型限制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复