我是靠谱客的博主 名字长了才好记,这篇文章主要介绍golang实现一个图片上传上传裁剪并加水印功能,现在分享给大家,希望可以做个参考。

下面是一个完整的 Golang 实现,使用 Gin 框架处理图片上传,然后进行裁剪和添加水印的功能。

功能概述

  1. 接收图片上传(支持 JPG/PNG)
  2. 对图片进行裁剪(可指定尺寸或保持比例)
  3. 添加文字或图片水印
  4. 保存处理后的图片

代码实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package main import ( "fmt" "image" "image/draw" "image/jpeg" "image/png" "io" "log" "net/http" "os" "path/filepath" "strings" "time" "github.com/disintegration/imaging" "github.com/gin-gonic/gin" "github.com/golang/freetype" "github.com/golang/freetype/truetype" "golang.org/x/image/font" "golang.org/x/image/math/fixed" ) const ( uploadDir = "./uploads" processedDir = "./processed" maxUploadSize = 10 << 20 // 10MB defaultQuality = 85 ) func init() { // 创建必要的目录 if err := os.MkdirAll(uploadDir, 0755); err != nil { log.Fatal(err) } if err := os.MkdirAll(processedDir, 0755); err != nil { log.Fatal(err) } } func main() { r := gin.Default() // 设置路由 r.POST("/upload", uploadHandler) r.GET("/image/:filename", getImageHandler) // 启动服务器 fmt.Println("Server started on :8080") if err := r.Run(":8080"); err != nil { log.Fatal(err) } } // 上传处理函数 func uploadHandler(c *gin.Context) { // 限制上传文件大小 c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxUploadSize) if err := c.Request.ParseMultipartForm(maxUploadSize); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "文件太大,最大支持10MB"}) return } // 获取上传的文件 file, header, err := c.Request.FormFile("image") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件"}) return } defer file.Close() // 检查文件类型 ext := strings.ToLower(filepath.Ext(header.Filename)) if ext != ".jpg" && ext != ".jpeg" && ext != ".png" { c.JSON(http.StatusBadRequest, gin.H{"error": "只支持JPG/PNG格式图片"}) return } // 生成唯一文件名 timestamp := time.Now().Unix() originalFilename := fmt.Sprintf("%d_original%s", timestamp, ext) processedFilename := fmt.Sprintf("%d_processed%s", timestamp, ext) // 保存原始文件 originalPath := filepath.Join(uploadDir, originalFilename) outFile, err := os.Create(originalPath) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "无法保存文件"}) return } defer outFile.Close() if _, err := io.Copy(outFile, file); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "无法保存文件"}) return } // 处理图片(裁剪和加水印) processedPath := filepath.Join(processedDir, processedFilename) if err := processImage(originalPath, processedPath); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "图片处理失败", "details": err.Error()}) return } // 返回响应 c.JSON(http.StatusOK, gin.H{ "message": "图片上传并处理成功", "original_image": originalFilename, "processed_image": processedFilename, }) } // 获取图片处理函数 func getImageHandler(c *gin.Context) { filename := c.Param("filename") processedPath := filepath.Join(processedDir, filename) // 检查文件是否存在 if _, err := os.Stat(processedPath); os.IsNotExist(err) { c.JSON(http.StatusNotFound, gin.H{"error": "图片未找到"}) return } // 提供图片文件 c.File(processedPath) } // 图片处理函数(裁剪+水印) func processImage(inputPath, outputPath string) error { // 打开原始图片 img, err := imaging.Open(inputPath) if err != nil { return fmt.Errorf("打开图片失败: %v", err) } // 1. 裁剪图片(示例:裁剪为300x300,从中心开始) img = imaging.Fill(img, 300, 300, imaging.Center, imaging.Lanczos) // 2. 添加文字水印 img, err = addTextWatermark(img, "Watermark Text") if err != nil { return fmt.Errorf("添加文字水印失败: %v", err) } // 3. 保存处理后的图片 ext := strings.ToLower(filepath.Ext(outputPath)) switch ext { case ".jpg", ".jpeg": err = imaging.Save(img, outputPath, imaging.JPEGQuality(defaultQuality)) case ".png": err = imaging.Save(img, outputPath) default: return fmt.Errorf("不支持的输出格式") } if err != nil { return fmt.Errorf("保存图片失败: %v", err) } return nil } // 添加文字水印 func addTextWatermark(img image.Image, text string) (*image.NRGBA, error) { // 加载字体(这里使用默认字体,实际项目中可以加载自己的字体文件) fontBytes := MustAsset("assets/fonts/Roboto-Regular.ttf") // 示例,需要提供字体文件 f, err := freetype.ParseFont(fontBytes) if err != nil { return nil, fmt.Errorf("解析字体失败: %v", err) } // 创建新的图像,复制原始图像 bounds := img.Bounds() watermarked := image.NewNRGBA(bounds) draw.Draw(watermarked, bounds, img, image.Point{}, draw.Src) // 设置水印参数 c := freetype.NewContext() c.SetDPI(72) c.SetFont(f) c.SetFontSize(24) c.SetClip(bounds) c.SetDst(watermarked) c.SetSrc(image.White) // 水印颜色 // 计算水印位置(右下角) pt := freetype.Pt(bounds.Dx()-200, bounds.Dy()-20) // 绘制水印 if _, err := c.DrawString(text, pt); err != nil { return nil, fmt.Errorf("绘制水印失败: %v", err) } return watermarked, nil } // 添加图片水印 func addImageWatermark(background, watermark image.Image, opacity float64) (*image.NRGBA, error) { bgBounds := background.Bounds() wmBounds := watermark.Bounds() // 创建新的图像,复制原始图像 watermarked := image.NewNRGBA(bgBounds) draw.Draw(watermarked, bgBounds, background, image.Point{}, draw.Src) // 计算水印位置(右下角) offset := image.Pt( bgBounds.Dx()-wmBounds.Dx()-10, bgBounds.Dy()-wmBounds.Dy()-10, ) // 应用水印(带透明度) draw.DrawMask( watermarked, wmBounds.Add(offset), watermark, image.Point{}, &image.Uniform{image.Alpha{uint8(opacity * 255)}}, image.Point{}, draw.Over, ) return watermarked, nil } // MustAsset 模拟加载字体文件(实际项目中应该从文件系统加载) func MustAsset(path string) []byte { // 这里应该从文件系统加载字体文件 // 示例中使用空字节,实际项目需要替换 return []byte{} }

依赖说明

  1. 使用了 Gin 框架处理 HTTP 请求
  2. 使用 disintegration/imaging 库进行图片处理
  3. 使用 golang/freetype 添加文字水印

安装依赖

复制代码
1
2
3
go get -u github.com/gin-gonic/gin go get -u github.com/disintegration/imaging go get -u github.com/golang/freetype

使用说明

  1. 启动服务器: go run main.go
  2. 使用 POST 请求上传图片到 /upload 端点表单字段名: image
  3. 处理后的图片会自动进行裁剪和添加水印
  4. 使用 GET 请求访问 /image/:filename 获取处理后的图片

扩展建议

  1. 添加更多图片处理选项(旋转、滤镜等)
  2. 支持配置水印样式(位置、大小、颜色等)
  3. 添加用户认证
  4. 实现图片元数据存储
  5. 支持批量处理
  6. 添加图片压缩功能
  7. 实现分布式处理

注意事项

  1. 文字水印需要提供字体文件(示例中的 MustAsset 函数需要实现)
  2. 图片水印功能需要提供水印图片
  3. 生产环境需要考虑安全性(文件类型检查、大小限制等)


最后

以上就是名字长了才好记最近收集整理的关于golang实现一个图片上传上传裁剪并加水印功能的全部内容,更多相关golang实现一个图片上传上传裁剪并加水印功能内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部