您的位置:

打造高效短网址|Base62编码工程实战案例

一、为什么需要短网址?

在现代社会,short url已不仅仅是保存空间和排版考虑的问题,更是一种需要在多个媒介传播的新闻、信息、产品宣传、宣传语的一种需求。

而常规的短网址转换基本都是通过跳转的方式实现,虽然看起来简单,但是每一个链接都要跳转一次,跳转次数多了还会给用户带来额外的时间成本,对于大流量网站而言,跳转次数多了会对服务器带来极大的负担,而且有时候并不是用户希望得到的目标页面,这时候就需要一种更有效的方式来实现短网址跳转。

此时就需要有一种更加高效和可靠的实现方式,比如 Base62 编码就是一种非常好的选择。

二、什么是Base62编码?

Base62编码是一种62进制的编码方式,使用数字、大小写字母来表示一个数字。

简单来说,就是将10进制的数字通过转换,用短字符串来表示该数字。可用于生成短网址、生成UID等场景。

Base62编码的值域为0-9a-zA-Z,共计62个字符,由于62的6次方比16的8次方大,所以base62在相同长度情况下能够表示的数字比base16要多得多,而且它的字符串相对长度也要短得多。

三、如何使用Base62编码实现短网址?

首先,我们需要将原始url转换为短码,以便在跳转时使用。一个有效的短网址方案应该包括以下两个环节。

第一步:生成短码:将原始长链接转换为短码。我们可以根据原始URL生成MD5值,然后通过Base62编码生成短码。

// 使用md5可以得到一个128位的哈希值,但使用Base62编码后只需要6位
unsigned char result[16];
md5(input, strlen(input), result);

// 计算生成的短码(使用 Base62 编码),即将 10 进制转换为 62 进制
std::string urlcode = hex2dec(result, sizeof(result));
std::string short_code = encode_base62((int)strtol(urlcode.c_str(), NULL, 16));

第二步:解析短码:请求缩短的短码,解析并有效的301定向到原始的长链接,这是一个经典的请求转发模式。

// 解析 Base62 编码得到 10 进制
unsigned long long count = decode_base62(shortCode);
std::stringstream ss;
ss << std::hex << count;
std::string s = ss.str();

// 补齐位数
std::string md5result(32 - s.length(), '0');
md5result = md5result + s;

// 将 16 进制字符串转换成 unsigned char[]
unsigned char result[16];
for (int i = 0; i < 16; i++)
{
    std::string sub = md5result.substr(i * 2, 2);
    result[i] = (unsigned char)strtol(sub.c_str(), NULL, 16);
}

// 通过 MD5 解析得到原始 URL
std::string url = md5_to_url(result);

通过以上两个步骤,我们就可以方便地将长链接转换为短链接,从而提高跳转效率。

四、完整代码示例

下面为完整的代码示例,包括了使用MD5生成哈希值以及Base62编码的实现。

#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include <cmath>
#include <algorithm>
#include <sstream>

const std::string base62_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

// Base62 编码
std::string encode_base62(unsigned long long number)
{
    std::string base62_str;
    do
    {
        base62_str.push_back(base62_chars[number % 62]);
        number /= 62;
    } while (number);

    std::reverse(base62_str.begin(), base62_str.end());
    return base62_str;
}

// Base62 解码
unsigned long long decode_base62(std::string const& str)
{
    unsigned long long number = 0;
    for (int i = 0; i < str.size(); ++i)
    {
        auto pos = base62_chars.find(str[i]);
        if (pos == std::string::npos)
            return 0;
        number += pos * pow(62, str.size() - i - 1);
    }
    return number;
}

// 将16进制字符串转换成unsigned char[]
unsigned char* hexstr_to_char(const char* source, unsigned char* dest)
{
    char h1, h2;
    unsigned char* ptr = dest;

    while (*source)
    {
        h1 = toupper(*source++);
        if (h1 == 0)
        {
            *ptr = 0;
            return dest;
        }

        h2 = toupper(*source++);
        if (h2 == 0)
        {
            *ptr = 0;
            return dest;
        }

        if ((h1 >= '0' && h1 <= '9') || (h1 >= 'A' && h1 <= 'F'))
            *ptr = (h1 <= '9') ? (h1 - '0') : (h1 - 'A' + 10);
        else
            break;

        *ptr <<= 4;

        if ((h2 >= '0' && h2 <= '9') || (h2 >= 'A' && h2 <= 'F'))
            *ptr |= (h2 <= '9') ? (h2 - '0') : (h2 - 'A' + 10);
        else
            break;

        ptr++;
    }

    return dest;
}

// 使用md5计算哈希值
void md5(const char* str, size_t len, unsigned char* result)
{
    EVP_MD_CTX* ctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
    EVP_DigestUpdate(ctx, str, len);
    EVP_DigestFinal_ex(ctx, result, NULL);
    EVP_MD_CTX_free(ctx);
}

// 将 md5 值转换成 URL
std::string md5_to_url(unsigned char* result)
{
    std::stringstream ss;
    for (int i = 0; i < 16; i++)
        ss << std::hex << (int)result[i];

    std::string url = ss.str();
    return url.substr(0, 8) + "-" + url.substr(8, 4) + "-" + url.substr(12, 4) + "-" + url.substr(16, 4) + "-" + url.substr(20);
}

int main()
{
    // 待转换的 URL
    std::string input = "https://www.google.com/";

    // 使用 md5 可以得到一个128位的哈希值,但使用 Base62 编码后只需要6位
    unsigned char result[16];
    md5(input.c_str(), input.length(), result);

    // 计算生成的短码(使用 Base62 编码),即将 10 进制转换为 62 进制
    std::string urlcode = hex2dec(result, sizeof(result));
    std::string short_code = encode_base62((int)strtol(urlcode.c_str(), NULL, 16));

    std::cout << "Short URL: " << short_code << std::endl;

    // 解析 Base62 编码得到 10 进制
    unsigned long long count = decode_base62(short_code);
    std::stringstream ss;
    ss << std::hex << count;
    std::string s = ss.str();

    // 补齐位数
    std::string md5result(32 - s.length(), '0');
    md5result = md5result + s;

    // 将 16 进制字符串转换成 unsigned char[]
    unsigned char result2[16];
    for (int i = 0; i < 16; i++)
    {
        std::string sub = md5result.substr(i * 2, 2);
        result2[i] = (unsigned char)strtol(sub.c_str(), NULL, 16);
    }

    // 通过 MD5 解析得到原始 URL
    std::string url = md5_to_url(result2);
    std::cout << "Original URL: " << url << std::endl;

    return 0;
}
打造高效短网址|Base62编码工程实战案例

2023-05-20
java笔记,尚硅谷java笔记

2022-12-01
java方法整理笔记(java总结)

2022-11-08
每日java学习笔记(java高手笔记)

2022-11-15
java学习笔记(java初学笔记)

2022-11-14
印象笔记记录java学习(Java成长笔记)

2022-11-12
java笔记,大学java笔记

2022-11-28
python课堂整理32(python笔记全)

2022-11-12
java学习的一些基础笔记(java初学笔记)

2022-11-14
Mac笔记:在日常生活中高效实用的笔记工具

2023-05-18
关于已前的学习笔记java的信息

2022-11-18
java高级工程师笔试题及答案(java中高级笔试题)

2022-11-15
Python Padx:用Python快速打造自己的代码笔记

2023-05-12
用c语言编写高考加油,用C语言编写高考加油代码

2022-11-25
python的学习笔记案例7(python例子)

2022-11-12
jspweb开发案例,jsp程序设计与案例实战

本文目录一览: 1、一个关于JSP脚本程序的案例 2、《JavaWeb开发实战1200例(第Ⅱ卷)》epub下载在线阅读,求百度网盘云资源 3、JSP基本语法 4、关于java如何做web应用程序开发

2023-12-08
cesiumjs详细教程(cesium开发教程)

本文目录一览: 1、Cesium在js中调用entity的infobox单机事件 2、Cesium初始化选项 3、Cesium随笔:视锥绘制(上) 4、cesium如何搭建dat.gui 5、Cesi

2023-12-08
java基础知识学习笔记一,Java基础笔记

2022-11-21
发篇java复习笔记(java课程笔记)

2022-11-09
短租网站管理系统php源码(php短网址程序源码)

2022-11-14