前言
最近刚学了使用一般处理程序生成带水印的图片,那也是打开本地图片。突然有个想法能不能直接根据网络上图片地址进行水印打印然后保存下来
大致思路
在输入框中黏贴上网络图片的url地址,在后台打开,对它进行打水印的操作。然后显示到前端,点下载按钮保存到计算机中。
实现
这里我们实现前端后端交互使用Ajax 和一般处理程序来完成。前端大致如下
<form id="form1" runat="server">
<div>
<table>
<tr>
<td>
<img src="#" id="img" />
图片地址:<asp:TextBox runat="server" ID="txt_url" Width="740px" ></asp:TextBox>
</td>
</tr>
</table>
</div>
</form>
<button id="btn">添加水印</button>
<button id="down">下载</button>
<input type="hidden" value="" id="imgvalue" />
<div id="main">
</div>
然后后端我们创建一个一般处理程序,在ProcessRequest方法中写一个判断,用于分别要使用的操作
再回到前端,为添加水印按钮绑定一个点击事件使用Ajax 访问后端的一般处理程序
简单说一下Ajax方法,第一个参数URL写我们要访问的一般处理程序action=url 是指这个请求是用于打印水印的方法,第二个参数data 里面的url是指我们要访问的请求地址 。
我们将后台获取到的打印水印的图片显示到前台,需要写在sucess:function(data){}里面。在这里后端返回的是一个base64字符串,所以我们需要创建一个img标签来进行展示。
参考博客:https://blog.csdn.net/fuyifang/article/details/52468099
在img的src属性中将前缀和从后端得到的base64字符串拼接起来就可以了。
后台生成base64
//这里写得到水印图片的代码
//在这需要对传过来的url末尾进行过滤
String url = context.Request.Params[“url”];
url = url.Replace(",/Handler1.ashx", “”);
if (url != null)
{
String bq = getbase64(url, context);
context.Response.Write(bq);
}
getbase64方法
public String getbase64(String url, HttpContext context)
{
String icon = “/img/icon.jpg”;
icon = context.Request.MapPath(icon);
//设置水印图片的大小
Bitmap bmicon = new Bitmap(50, 50);
//加载图标
Graphics g = Graphics.FromImage(bmicon);
//对图片进行缩放处理
g.DrawImage(Image.FromFile(icon), 0, 0, 50, 50);
//根据url资源,将其在内存中打开
WebRequest request = HttpWebRequest.Create(url);
WebResponse web = request.GetResponse();
Stream stream = web.GetResponseStream();
//打开图片
Image img = Image.FromStream(stream);
//创建一个Bitmap对象
Bitmap bmp = new Bitmap(img);
//对 原始图片进行绘制
Graphics ggs = Graphics.FromImage(bmp);
//加入图标
ggs.DrawImage(bmicon, bmp.Width - bmicon.Width, bmp.Height - bmicon.Height, 50, 50);
//绘制文字
ggs.DrawString("起飞,起飞怎么说", new Font("宋体", 20), Brushes.Red, new Point(60, 10));
//创建一个内存流
MemoryStream ms = new MemoryStream();
//将修改的图像保存到内存流
bmp.Save(ms, ImageFormat.Jpeg);
byte[] by = new byte[ms.Length];
ms.Position = 0;
ms.Read(by, 0, (int)ms.Length);
return Convert.ToBase64String(by);
}
现在去随便去弄个图片url测试一下,会显示成这样
这样打印水印就完成了。
接下来的下载水印到本地就就简单多了。
在为下载按钮绑定一个点击事件
$("#down").click(function () {
var img = $("#txt_url").val();
$.ajax({
url: “Handler1.ashx?action=down”,
data: { data:img },
dataType: “text”,
success: function (data) {
alert(data);
}
});
});
这里注意要更改action的值
一样的将文本框中的url传到后台的一般处理程序处理。
else if(action.Equals(“down”))
{
//这里写下载图片的代码
String url = context.Request.Params[“data”];
String img = getbase64(url, context);
img = img.Replace(“data:image/jpeg;base64,”, “”);
byte[] by = Convert.FromBase64String(img);
String filename = “d:/test/”;
//对目录进行判断,没有该目录就创建
if(Directory.Exists(filename)==false)
{
Directory.CreateDirectory(filename);
}
String imgpath = filename + DateTime.Now.ToString(“yyyyhhddmmss”)+".jpg";
try
{
File.WriteAllBytes(imgpath, by);
context.Response.Write(“保存成功!地址在” + imgpath);
}
catch(Exception e)
{
context.Response.Write(“发送异常保存失败”);
}
}
显示效果是这样的
ok现在就保存好了。
缺点
只能用于没有设置防盗链的图片。
水印形式定死了,不够灵活。
img 的 显示形式也写死了,用的jpeg形式。
等等。
最后总结
这个想法一开始做的并不顺利,我在使用Ajax访问一般处理程序时候,在方法里面得到的url后面不知道为啥会有类名,因为url路径的错误导致后面生成的图片一直是黑的。就卡在哪半天,用debug在哪里看了好久才发现转换的byte数组的长度有问题,仔细看了看访问路径才发现是错的。后面加了个字符串过滤才弄好的。下载图像哪里一开始也有个问题,本来一开始设计是想要把得到的base64字符串存到一个隐藏的input框中,再下载的时候将它作为参数传到后台去直接保存到本地,结果运行发现压根用不了,断点打在里面,进都进不去。后面无奈只好再调用一次生成水印图片的方法,将其保存到本地,性能可能就不是很理想。