最近 新浪和腾讯短网址的接口不能用了,所以打算自己弄个短网址服务玩玩(个人使用而已)
环境
服务器: 很渣的一台windos服务器 (腾讯云买的很便宜的那种)
项目: .net WebApi(vs直接创建,再删掉一些多余的东西)
数据库:Redis(换其他数据库也可以)需要去网上下载windos版本的,我是网上随便找的5.09版本
域名:一个(已备案的)
核心:
1.短网址的算法(看了好多文章的)
网上说的有两种,一种是id自增,另一种是通过长链接做一些操作运算(我采用的这种)
算法如下(网上找的,随便搜应该一大堆):
//短网址映射算法:
//将长网址md5生成32位签名串,分为4段,每段8个字节;
//对这四段循环处理,取8个字节,将他看成16进制串与0x3fffffff(30位1)与操作,即超过30位的忽略处理;
//这30位分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串;
//总的md5串可以获得4个6位串;取里面的任意一个就可作为这个长url的短url地址;
//并不一定说得到的URL是唯一的,但能够取出4组URL,不会出现太大的重复。
代码应该就不需要放出来吧
2.redis的存储与读取
使用 Redis 需要先在本地(或远程)开启
引入几个dll:
ServiceStack.Redis.dll
ServiceStack.Text.dll
ServiceStack.Common.dll
ServiceStack.Interfaces.dll
如果执行会报错可能还得再引入 System.Memory.dll 具体看异常
这次项目比较简单的只有用到了两个方法,
//dt 是过期时间 db是哪个数据库
public static bool SetValue(string key, string value, DateTime dt, int db = 0)
{
using (RedisClient redisClient = new RedisClient(host, 6379, password, db))
{
return redisClient.Set(key, value, dt);
}
}
public static string GetValue(string key, int db = 0)
{
using (RedisClient redisClient = new RedisClient(host, 6379, password, db))
{
return redisClient.GetValue(key);
}
}
把 算法计算出的值(取其中一个) 作为 key,长链接 作为 value,再设置个过期时间(这里数据存的比较简单)
3.webapi的设置
项目里还得修改路由(WebApiConfig),让 xxxx.cn/abcd 是短链接重定向接口,默认是Home/index,改完之后可能会影响其它接口访问路径,这个就自己看着改 - -、
项目里有两个接口一个生成,一个跳转:
[HttpGet]
public IHttpActionResult GetLongLink(string code)
{
if (string.IsNullOrWhiteSpace(code))
{
return Redirect(Request.RequestUri.AbsoluteUri.ToString()+"Home/Index");//跳转到Home/index
}
var longlink=Redis.GetValue(code).Replace("\"","");//取出来的带有\"所以去掉它
if (string.IsNullOrWhiteSpace(longlink))
{
return Json(new { error = 1,msg="链接已经失效" });
}
return Redirect(longlink);
}
[HttpGet]
public IHttpActionResult GetShortLink(string longlink)
{
if (string.IsNullOrWhiteSpace(longlink))
{
return Json(new { error = 1,msg="长链接不能为空" });
}
if (longlink.IndexOf("http://") != 0 && longlink.IndexOf("https://") != 0)
{
return Json(new { error = 1, msg = "长链接格式有误" });
}
var shortCode=Utils.ShortUrl(longlink)[0];//短网址算法计算出的值拿第一个
Redis.SetValue(shortCode, longlink,DateTime.Now.AddDays(30));
var shortlink = Request.RequestUri.Authority.ToString()+"/" + shortCode;//拼接完整的链接(这里不带http不过没啥影响,需要的话也可以拼上去)
return Json(new { error=0,msg="成功", shortlink });
}
生成短链接接口的参数longlink需要编码才能传入,不然参数可能会被截断