一、為什麼需要短網址?
在現代社會,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 = '0' && h1 = 'A' && h1 <= 'F'))
*ptr = (h1 <= '9') ? (h1 - '0') : (h1 - 'A' + 10);
else
break;
*ptr <= '0' && 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;
}
原創文章,作者:BVMQC,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/324850.html