使用 golang 以及 Gin 框架,将上传的图片在不保存至本地的情况下添加水印,并上传至阿里云 OSS

news/2024/6/16 11:34:14/文章来源:https://blog.csdn.net/coco2d_x2014/article/details/137182269

正如标题所述,使用golang对上传图片添加水印,以及将图片上传到阿里云OSS,网上一搜索,便有你想要的结果了,可是,他们却先将上传图片添加水印后保存在本地,而后再将添加了水印的图片上传到阿里云OSS

这无疑是暂时占用了你电脑的磁盘空间(这里说是暂时,因为你可以通过程序对上传到阿里云OSS成功的图片进行删除),即便是这样,它也是消耗了磁盘读写操作,虽然人类是察觉不到这么细微的变化。

然而,作为技术人员的我们(不介意我这么称呼自己吧!),使能够Review出这段程序的问题。很显然,本地图片是要通过程序处理,添加水印,而后最终储存到阿里云OSS中,而不是又要在本地多存了一张比原图多了些水印的图片。

图像处理库

既然我们的目的明确了,那么就卷起柚子加油干吧!

虽然,使用golang对上传图片添加水印,以及如何将图片上传到阿里云OSS中,是两个独立分开的。但是,这两步看似分而食之的程序,其实是可以合二为一的!(我想,正在浏览本文的你,也是这么想的!)

这是可行的方案,毕竟先前的秋码记录 就是这么做的(那是使用Java构建的那些年!当然现在的 秋码记录 改用 ```Hugo·``搭建了)。

既然,java能实现对上传图片添加水印,而不暂时保存在本地,立马即可上传到阿里云OSS中。想必,golang也是可以完成的!

然而,网上相关的资料有限,才能铸就本文的诞生!

首先,我是用golang的版本是1.19,虽然不是最新的,但却不妨碍我们继续对本文的讲解。

虽然,人类总是对新鲜事物充满好奇,从而萌生了猎奇心。但也只有在旧事物的烘衬下,人们才能对新事物寄以最大的希望!这就好比,老婆总是别人的好看(当然,别人的老婆也有没有自己老婆好看的),这才造就了黄脸婆这一全国男人在没有老婆在身旁统一叹息声!

你得在你电脑任一磁盘下,新建一空文件夹,随后打开黑窗口(Terminal),输入以下命令,说明是modules进行管理的(毕竟我使用的是golang 1.19):

go mod init qiucode.cn/uploadImage

对于以上这行命令,就是初始化golang模块(module),在golang的世界是```万物皆可模块``(我说的如果不对,那么说出你的想法)。

初始化项目后,我们会发现文件夹下多了个go.mod文件(这个就是用来管理第三方依赖库的管理文件,不需要操作!),在该同级目录下新建main.go文件。

既然本文是探讨如何实现图片添加水印的,那么引入图像库那是必不可少的!

go get github.com/fogleman/gg

本文不会对这个图像库进行深层次的讲解!毕竟本文的核心内容是介绍如何对图片添加水印,而不是避重就轻本末倒置讲起了本该一笔带过的东西,却花了浓墨重彩去着重的描绘刻画它,到头来,却失了初心,乱了本文的主旨,实属不该。(实在不清楚的,可以去查看其文档)

很显然,将图片上传到阿里云OSS上,引入其SDK,那是必不可少的(关于这一点,应该不需要我多费口舌了吧)

go get github.com/aliyun/aliyun-oss-go-sdk/oss

接下来的这个依赖库,并不是必须的(那就是可选的),毕竟,有它没有它,本文都可以实现!

go get github.com/gin-gonic/gin

是啊!都说了,不引入它,本文也可以实现,那么我为什么还引入了呢?(关于这一点,欢迎你能在评论中留下你的只言片语,请不要吝啬你的文字!)

用代码实现标题的需求

前提准备工作就绪,我们该正式进入编码环节了。到了这里,正处于屏幕前的你,想必早就迫不及待了吧!毕竟,你就是与我有同样的需求,才会浏览本文的(当然也有那种,鼠标不小心点到了,但那种几率是很小的,我相信你不是属于那一类的)

首先,我们使用VS Code(你也可以使用其他你平时常用的IDE,不必非要使用与我一样的VS Code,然而,作为一款开源免费的IDE,你还有什么理由不去使用它呢?哦,差点忘记了,都说了,使用IDE是个人的自由,可我这么一说,倒有了让你使用VS Code之嫌。虽然,或许你比较喜欢使用收费软件,但你都是找的破解方法来破解软件,从而使用它们)

打开刚刚新建的main.go文件,开始逐步实现标题的需求。

package mainimport ("bytes""image""image/png" // "image/jepg"  //用于对 jpg 格式的图片进行处理 本文暂时不对 jpg 图片做处理"github.com/gin-gonic/gin"  //web 框架"github.com/fogleman/gg"  // 图像处理哭"github.com/aliyun/aliyun-oss-go-sdk/oss" //阿里云OSS SDK
)

随后,我们在main函数中实现标题中的需求。

func main() {r := gin.Default()r.MaxMultipartMemory = 8 << 20 // 8 MiBr.Static("/", "./public")r.POST("/upload", func(c *gin.Context) {// 获取用户上传文件file, err := c.FormFile("editormd-image-file")if err != nil {c.JSON(500, gin.H{"message":  "err:"+ err.Error()})return}// file.Filename 就是原始的文件名originalFilename := file.Filename// 做一些处理,例如打印文件名println("Uploaded file: " + originalFilename)src, err2 := file.Open()if err2 != nil {c.JSON(500, gin.H{"message":  "err2:"+ err2.Error()})return}defer src.Close()// 将文件转化为image.Image,添加水印img, _, err3 := image.Decode(src)if err3 != nil {c.JSON(500, gin.H{"message":  "err3:"+ err3.Error()})return}println("%d | %T",img.Bounds().Dx(),img.Bounds().Dx())imgWidth := img.Bounds().Dx()imgHeight := img.Bounds().Dy()dc := gg.NewContext(imgWidth, imgHeight)dc.DrawImage(img, 0, 0)dc.SetRGB(118,104,104)err4 := dc.LoadFontFace("aparaj.ttf", 48)if err4 != nil {c.JSON(500, gin.H{"message": "err4:"+ err4.Error()})return}// 旋转文本 以图像正中为中心旋转dc.RotateAbout(gg.Radians(-40), float64(imgWidth/2), float64(imgHeight/2)) W := int(imgWidth)H := int(imgHeight)text := "https:;//qiucode.cn" //水印文字// 计算水印文本的尺寸textWidth := float64(len(text)) * 20 // 20 是字体大小  可自行修改const S = 60 // 水印文本的大小for y := -H; y < H; y += S {for x := -H; x < W*2; x += int(textWidth) { // 根据文本尺寸调整x轴的绘制间距dc.DrawStringAnchored(text, float64(x), float64(y), 0.5, 0.5)}}//循环添加水印 enddc.SetLineWidth(2)dc.Stroke()// 创建字节缓冲区并将图像编码为PNGbuf := new(bytes.Buffer)err5 :=png.Encode(buf, dc.Image())if err5 != nil {c.JSON(500, gin.H{"message":  "err5:"+ err5.Error()})return}endpoint := "这里是您的 endpoint "  // 这里的是广州区,accessKeyID := "您阿里云的 accessKeyID "   accessKeySecret := "您阿里云 accessKeySecret"   bucketName := "qiucodeimg";//文件存储目录filedir := "golang-test/";// 创建OSS clientclient, err6 := oss.New(endpoint, accessKeyID, accessKeySecret)if err6 != nil {c.JSON(500, gin.H{"message":  "err6:"+ err6.Error()})return}// 获取存储空间bucket, err7 := client.Bucket(bucketName)if err7 != nil {c.JSON(500, gin.H{"message":  "err7:"+ err7.Error()})return}objectKey := filedir + originalFilename// 上传文件流bucket.PutObject(objectKey, bytes.NewReader(buf.Bytes()))// 生成签名的 URLsignedURL, err8 := bucket.SignURL(objectKey, oss.HTTPGet, 600)if err8 != nil {c.JSON(500, gin.H{"message":  "err8 :"+ err8.Error()})return}c.JSON(200, gin.H{"success": 1,"message": "上传成功","url": signedURL, //将成功上传到阿里云OSS的图片 URL 返回给页面})})// 使用  8080 端口进行监听r.Run(":8080")
}

对于以上代码,你看完后,想必有很多话要说吧!没错,可以将图片添加水印的抽取成一个函数,还有的是就是需要判断上传的图片格式,是PNG还是JPEG等格式……

然而,你似乎忘记了,本文已经将原本两个各自独立的,合二为一而且还实现了,至于抽取成函数,上传图片格式判别,就让正在浏览本文的您,或还苦苦找寻怎么使用golang实现对上传图片添加水印并上传到阿里云OSS挠头托腮的!本文的实现将你们的福音,也将是你们的一剂强心针(总算是找到了一篇关于怎么使用golang实现了公司的需求)

差点忘记了,还用静态资源,使用了开源的 editormd。https://github.com/pandao/editor.md 。

在这里插入图片描述

以及 index.html文件内容。

在这里插入图片描述

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><link href="/static/editormd/css/editormd.css" type="text/css" rel="stylesheet">
</head>
<body><div id="test-editor"><textarea style="display: none;" name="context"></textarea>
</div></body><script src="./static/jquery-3.4.1/jquery-3.4.1.min.js"></script>
<script type="text/javascript" charset="utf-8"  src="./static/editormd/editormd.min.js"></script><script>var editor;$(function () {editor = editormd("test-editor", { //注意1:这里的就是上面的DIV的id属性值width: "90%",height: 750,syncScrolling: "single",path: "/static/editormd/lib/", //注意2:你的路径saveHTMLToTextarea: true ,//注意3:这个配置,方便post提交表单imageUpload : true,imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],imageUploadURL : "/upload",});});
</script></html>

最后,还是贴出效果图。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1034090.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

火鸟门户系统—房产门户板块

房产门户简介 房产门户是提供房产信息和服务的网站或应用程序。房产门户通常提供以下功能&#xff1a; 房产搜索&#xff1a;用户可以根据位置、价格、房型等条件搜索房产信息。房产发布&#xff1a;用户可以发布出售或出租的房产信息。经纪人查询&#xff1a;用户可以查询附…

“两化”融合试点名单汇总数据(2014至2018年)

01、数据简介 两化融合是指信息化和工业化的高层次的深度结合&#xff0c;其核心在于信息化支撑&#xff0c;追求可持续发展模式。 “两化”融合贯标试点只针对制造业企业&#xff0c;解释变量“两化”融合贯标试点数据来自工业和信息化部办公厅公布的试点名单以及“两化融合…

动态规划训练1

一、leetcode 91解码方法 1、题目解析 这道题就是需要我们对一个数组进行解码&#xff0c;返回有多少种方法就行了。 但是有几个特殊情况&#xff1a;06 不可以为一组、60 也不可以、6 、0也不行 2、算法原理 a状态表示 根据经验题目要求确定表示方程 以i位置为结尾&…

雷军之夜:小米汽车SU7发布会后的智能化探索与网络安全考量

引言 3月28日晚&#xff0c;小米集团创始人雷军在一场备受瞩目的发布会上&#xff0c;以其一贯的激情与诚意&#xff0c;揭开了小米汽车首款车型SU7的神秘面纱。这一夜&#xff0c;不仅是小米跨足汽车行业的重要里程碑&#xff0c;更是中国智能汽车产业向前迈进的新篇章。然而…

【隐私计算实训营008——SCQL】

1.SCQL使用/集成最佳实践 目前SCQL只开放API供用户使用/集成 使用SCDBClient上手体验可以基于SCQL API开发封装白屏产品&#xff0c;或集成到业务链路中 1.1 部署系统 环境配置&#xff1a; 机器配置&#xff1a;CPU/MEM最低8C16G机构之间的网络互通 镜像&#xff1a;secret…

Golang生成UUID

安装依赖 go get -u github.com/google/uuid文档 谷歌UUID文档 示例 函数签名func NewV7() ( UUID ,错误) func (receiver *basicUtils) GenerateUUID() uuid.UUID {return uuid.Must(uuid.NewV7()) } uid : GenerateUUID()

docker部署实用的运维开发手册

下载镜像 docker pull registry.cn-beijing.aliyuncs.com/wuxingge123/reference:latestdocker-compose部署 vim docker-compose.yml version: 3 services:reference:container_name: referenceimage: registry.cn-beijing.aliyuncs.com/wuxingge123/reference:latestports:…

【日常记录】【CSS】css文字渐变擦除

文章目录 1、代码2、自定义css属性 1、代码 主要思路是&#xff1a; 1、弄一个一样的&#xff0c;覆盖到上面去 2、然后改一下文字颜色&#xff0c;改成透明&#xff0c;背景颜色改成 渐变&#xff0c;可以从透明到一个实色&#xff0c;这样就能显示出来下面的文字 3、只有 行内…

百度网站收录提交入口

百度网站收录提交入口 在网站刚建立或者更新内容后&#xff0c;及时将网站提交给搜索引擎是提高网站曝光和获取流量的重要步骤之一。百度作为中国最大的搜索引擎之一&#xff0c;网站在百度中的收录情况尤为重要。下面介绍一下如何通过百度的网站收录提交入口提交网站。 1. 百…

C#手术麻醉系统源码 大型医院手麻系统4大需求是什么?

C#手术麻醉系统源码 大型医院手麻系统4大需求是什么&#xff1f; 手术麻醉临床信息系统有着完善的临床业务功能&#xff0c;能够涵盖整个围术期的工作&#xff0c;能够采集、汇总、存储、处理、展 现所有的临床诊疗资料。通过该系统的实施&#xff0c;能够规范手麻科的工作流程…

PTA L2-045 堆宝塔

堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小&#xff0c;按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。聪明宝宝采取的策略如下&#xff1a; 首先准备两根柱子&#xff0c;一根 A 柱串宝塔&#xff0c;一根 B 柱用于临时叠放。把第 1 块彩虹圈…

MATLAB科研绘图与学术图表绘制从入门到精通

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

Mybatis plue(二) 核心功能

核心功能 P5 条件构造器 mybatisplus支持各种复杂的where条件&#xff0c;可以满足日常开发的所有需求 wrapper就是条件构造器,wrapper就是顶层的&#xff0c; 示例&#xff1a; 查询出名字带0&#xff0c;存款大于等于1000的人的id,username,info,balance字段 Testvoid te…

Oracle Cloud公布 | 每小时 126 亿次 SQL 数据库查询

广而告之&#xff1a;2024 年数据技术嘉年华大会将于 4 月12-13 日在北京召开&#xff0c;春暖花开之际&#xff0c;数据库行业蓬勃发展之时&#xff0c;广邀天下豪杰&#xff0c;相聚北京&#xff0c;共论数据库技术发展的创新与未来。 注册&#xff1a;https://www.modb.pro/…

Adaboost集成学习 | Matlab实现基于GRU-Adaboost门控循环单元结合Adaboost集成学习时间序列预测(股票价格预测)

目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 Adaboost集成学习 | Matlab实现基于GRU-Adaboost门控循环单元结合Adaboost集成学习时间序列预测(股票价格预测) 模型设计 股票价格预测是一个具有挑战性的时间序列预测问题,可以使用深度学习模型如门控循环…

安卓Android 架构模式及UI布局设计

文章目录 一、Android UI 简介1.1 在手机UI设计中&#xff0c;坚持的原则是什么1.2 安卓中的架构模式1.2.1 MVC (Model-View-Controller)设计模式优缺点 1.2.2 MVP(Model-View-Presenter)设计模式MVP与MVC关系&#xff1a; 1.2.3 MVVM(Model—View—ViewModel ) 设计模式1.2.4 …

视觉里程计之对极几何

视觉里程计之对极几何 前言 上一个章节介绍了视觉里程计关于特征点的一些内容&#xff0c;相信大家对视觉里程计关于特征的描述已经有了一定的认识。本章节给大家介绍视觉里程计另外一个概念&#xff0c;对极几何。 对极几何 对极几何是立体视觉中的几何关系&#xff0c;描…

政务AI交互数字人推动政务“人工智能+”建设

传统的政务平台大多是单向与用户互动&#xff0c;缺乏即时反馈&#xff0c;导致用户需要花费大量时间理解信息&#xff0c;并难以提出问题得到及时解答。 AI交互数字人凭借其智能性&#xff0c;可以在政务网页、政务业务办理大厅一体机、政务APP/小程序等终端设备中&#xff0…

OSPF中配置静态路由实验简述

静态路由协议和OSPF&#xff08;开放最短路径优先&#xff09;协议是两种常见的路由协议&#xff0c;它们在路由选择和网络管理方面有一些区别。他们可以共存。 静态路由协议需要手动配置路由表&#xff0c;不会自动适应网络拓扑变化&#xff0c;适用于小型网络或者网络拓扑变化…

非关系型数据库(缓存数据库)redis的基础认知与安装

目录 一.关系型数据库和非关系型数据库 关系型数据库 非关系型数据库 关系数据库与非关系型数据库的区别 ①非关系数据 关系型数据库 非关系型数据库产生背景 数据存储流向 非关系型数据库 关系数据库 二.redis的简介 1.概念 2.Redis 具有以下几个优点: 3.Redi…