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框架实现上传和水印增加常见图片类型限制内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复