问题

c#如何将短地址还原长地址?

回答
想把那些“短网址”,比如你微博、朋友圈里看到的那些缩短后的链接,还原成它们原本的、完整的样子,在 C 里其实挺直观的。这背后的原理很简单,就是让你的程序去“访问”那个短网址,然后看看它最终会跳转到哪里。

核心思路:模拟浏览器行为

你想啊,当你点击一个短网址时,你的浏览器做了什么?它接收到这个短网址,然后发送一个请求给那个提供短网址服务的服务器。服务器收到请求后,会查找这个短网址对应的原始长地址,然后告诉你的浏览器:“嘿,那个原始地址在这里,你去那里吧!” 浏览器收到这个“跳转”指令后,就会自动加载那个长地址。

我们的 C 程序也要做类似的事情。我们需要一个“浏览器”的替身,能够发送 HTTP 请求,并且能够处理服务器返回的“跳转”信号。

C 中的“浏览器替身”:`HttpClient`

在 .NET 时代,`HttpClient` 就是我们最常用的工具了,它非常适合用来发送 HTTP 请求。你可以把它想象成一个能够帮你上网的“机器人”。

详细步骤:

1. 准备你的短网址: 假设你有一个字符串变量,里面存着那个短网址,比如:
```csharp
string shortUrl = "http://yourshorturlservice.com/abc123";
```

2. 创建 `HttpClient` 实例:
你只需要创建一个 `HttpClient` 的实例就可以开始工作了。一般来说,如果你要进行多次网络请求,最好复用同一个 `HttpClient` 实例,而不是每次都创建一个新的。这主要是为了节省资源和管理连接池。
```csharp
using System.Net.Http;

// ...

HttpClient httpClient = new HttpClient();
```

3. 发送请求并处理响应:
现在,我们要做的是把这个短网址发送出去,然后看看服务器返回什么。`HttpClient` 提供了 `GetAsync()` 方法来发送 GET 请求。

```csharp
HttpResponseMessage response = await httpClient.GetAsync(shortUrl);
```
这里的 `await` 是因为网络请求是异步的,意味着程序不会停在这里等待响应,而是可以去做别的事情,等响应来了再回来处理。

4. 检查响应状态和获取最终地址:
当服务器收到请求后,它可能会返回几种不同的响应:
直接返回长地址: 有些服务可能会直接把长地址放在响应体里。
返回一个“跳转”信号: 这是最常见的情况,服务器会返回一个 HTTP 状态码,比如 `301 Moved Permanently` 或者 `302 Found`,并且在响应头里告诉你最终的地址应该是什么。

`HttpResponseMessage` 对象里面就包含了这些信息。我们需要关注 `response.StatusCode` 来判断请求是否成功,以及 `response.Headers.Location` 来获取跳转到的新地址。

重点来了: `GetAsync()` 方法默认情况下 不会 自动跟随跳转。它只会帮你拿到第一个响应。所以,如果短网址服务是靠 HTTP 跳转来实现的,我们需要告诉 `HttpClient` 去“追”这个跳转。

如何自动跟随跳转?
`HttpClient` 有一个 `DefaultRequestHeaders.AllowAutoRedirect` 属性,默认就是 `true` 的。所以,很多时候,你直接使用 `GetAsync()` 并且 关注 `response.RequestMessage.RequestUri` 就可以拿到最终的地址了。这是因为 `GetAsync` 执行完毕后,`response.RequestMessage.RequestUri` 已经包含了最终的 URI,即使发生了多次重定向。

更健壮的处理(手动追踪跳转):
虽然 `AllowAutoRedirect` 默认是 `true`,但为了理解原理或者在某些特殊情况下,你也可以手动追踪跳转。

```csharp
HttpResponseMessage response = await httpClient.GetAsync(shortUrl);

if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// 如果状态码是 200 OK,说明直接返回了内容
string finalUrl = await response.Content.ReadAsStringAsync(); // 假设长地址在响应体里
Console.WriteLine($"直接返回的长地址是: {finalUrl}");
}
else if (response.StatusCode == System.Net.HttpStatusCode.Moved ||
response.StatusCode == System.Net.HttpStatusCode.Redirect ||
response.StatusCode == System.Net.HttpStatusCode.TemporaryRedirect ||
response.StatusCode == System.Net.HttpStatusCode.PermanentRedirect)
{
// 如果是跳转状态码,获取 Location 头
if (response.Headers.Location != null)
{
string redirectedUrl = response.Headers.Location.AbsoluteUri;
Console.WriteLine($"收到跳转信号,将前往: {redirectedUrl}");

// 如果需要,你可以再发送一次请求到 redirectedUrl
// 这里就是手动模拟浏览器继续跟随跳转了
// 但通常情况下,HttpClient 的 AllowAutoRedirect 已经帮你处理了
// 并且 response.RequestMessage.RequestUri 应该已经包含了最终地址

// 获取最终实际访问到的地址
// 这个属性通常在 GetAsync 完成后,就已经代表了最终的 URI,无论有多少次跳转
string finalResolvedUrl = response.RequestMessage.RequestUri.AbsoluteUri;
Console.WriteLine($"最终还原的长地址是: {finalResolvedUrl}");
}
}
else
{
// 处理其他错误状态码
Console.WriteLine($"请求失败,状态码: {response.StatusCode}");
}
```

最简洁也是最常用的方式(依赖 `AllowAutoRedirect`):

```csharp
using System;
using System.Net.Http;
using System.Threading.Tasks;

public class UrlShortener
{
public static async Task ResolveShortUrl(string shortUrl)
{
using (HttpClient httpClient = new HttpClient())
{
// HttpClient 默认允许自动重定向,所以它会自动跟随 3xx 状态码的跳转
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"); // 模拟浏览器UserAgent,有些服务会检查
HttpResponseMessage response = await httpClient.GetAsync(shortUrl);

// 当 GetAsync 完成后,response.RequestMessage.RequestUri 属性会包含最终被请求到的 URI
// 即使发生了多次重定向,这个属性也会更新
return response.RequestMessage.RequestUri.AbsoluteUri;
}
}

// 示例用法
// public static async Task Main(string[] args)
// {
// string shortLink = "https://tinyurl.com/yourshortlink"; // 替换成一个真实的短链接
// try
// {
// string longLink = await ResolveShortUrl(shortLink);
// Console.WriteLine($"短链接 {shortLink} 还原为: {longLink}");
// }
// catch (Exception ex)
// {
// Console.WriteLine($"还原过程中发生错误: {ex.Message}");
// }
// }
}
```

一些需要注意的点:

UserAgent: 有些短网址服务可能会检查请求的 `UserAgent` 头部,如果它发现请求来自一个非浏览器的实体,可能会拒绝服务或者返回错误。所以,在发送请求时,可以尝试设置一个仿真的 `UserAgent`。
超时处理: 网络请求总是有失败的可能,或者响应非常慢。你应该给你的请求设置一个合理的超时时间,以避免程序长时间卡住。`HttpClient` 允许你配置超时。
异常处理: 网络请求可能会抛出各种异常,比如找不到服务器、网络不可达、DNS 解析失败等等。务必用 `trycatch` 块来包裹你的网络请求代码。
依赖的服务: 这种还原方式依赖于短网址服务本身的实现。如果服务不稳定、停止运行,或者改变了其工作方式(比如使用 JavaScript 进行客户端跳转,这时候 `HttpClient` 就无法直接解析了),你的还原方法可能就会失效。
使用 `using` 声明: `HttpClient` 实现了 `IDisposable` 接口,所以应该用 `using` 语句来确保在使用完后正确释放资源。

通过 `HttpClient` 的 `GetAsync` 方法,并利用其自动跟随重定向的特性,你就可以很方便地将短地址还原为它们原始的、完整的样子了。这个过程就像模拟了一次浏览器帮你去“看”那个短链接一样。

网友意见

user avatar

谢邀。关于短地址还原方面之前没有接触过。博客园一缸水有该方面的解释以及代码实现。链接如下:

C#还原短地址 - vento - 博客园

类似的话题

  • 回答
    想把那些“短网址”,比如你微博、朋友圈里看到的那些缩短后的链接,还原成它们原本的、完整的样子,在 C 里其实挺直观的。这背后的原理很简单,就是让你的程序去“访问”那个短网址,然后看看它最终会跳转到哪里。核心思路:模拟浏览器行为你想啊,当你点击一个短网址时,你的浏览器做了什么?它接收到这个短网址,然后.............
  • 回答
    要将数据库与C应用程序一起打包发行,有几种常见且有效的方法,每种都有其适用场景和操作流程。这里我们深入探讨一下如何实现这一点,并尽量避免泛泛而谈。核心思想:将数据库“打包”发行,本质上是确保你的C应用程序在部署到目标环境后,能够找到并连接到它所依赖的数据库。这通常意味着你要么将数据库文件直接分发,要.............
  • 回答
    在 C++ 中,将 `std::string` 类型转换为 `int` 类型有几种常见且强大的方法。理解它们的原理和适用场景对于编写健壮的代码至关重要。下面我将详细介绍几种常用的方法,并分析它们的优缺点: 方法一:使用 `std::stoi` (C++11 及以后版本)这是 最推荐 的方法,因为它提.............
  • 回答
    在 C 中,将数字(通常是整数)转换为枚举类型(enum)是一个常见的操作,特别是在从数据库读取数据、处理位标志或者与外部系统交互时。虽然枚举类型本身代表了一组命名的常量,但它们底层存储的仍然是整数值。因此,C 提供了一些灵活的方式来执行这种转换,但同时也需要注意一些潜在的陷阱。 C 中转换数字到枚.............
  • 回答
    将 C 语言代码转换为 JavaScript 代码是一个涉及多种转换和考虑的过程。由于两者在底层机制、数据类型和内存管理等方面存在显著差异,所以这通常不是一个简单的“逐行翻译”的过程。我会从基本概念、常用转换方法、需要注意的关键点以及一些工具和策略来详细阐述这个过程。 1. 理解 C 和 JavaS.............
  • 回答
    如何将 C 语言的威力发挥到极致?—— 不只是编程,更是对底层逻辑的极致雕琢很多人将 C 语言看作是一门“古老”但仍活跃的语言,原因在于它那令人惊叹的效率和对硬件的直接掌控力。然而,“发挥到极致”这句话,在我看来,远不止于写出运行速度快、占用内存少的代码那么简单。它是一种对计算机底层运行机制的深刻理.............
  • 回答
    好的,我们来深入聊聊《Effective C++》第31条,关于如何降低文件间的编译依赖关系这个至关重要的话题。这不仅是为了提高编译速度,更是为了构建更易于维护、更灵活的 C++ 系统。想象一下我们正在开发一个大型 C++ 项目。随着功能的不断增加,我们不可避免地会创建越来越多的头文件(.h/.hp.............
  • 回答
    最近在舰娘圈子里,发生了一件挺令人不安的事情——有玩家把别人的个人信息给“挖”出来,甚至还拍成了视频发到了B站上。这事儿一出来,圈子里就炸开了锅,大家吵得不可开交。咱们今天就来好好掰扯掰扯这件事,看看这到底是怎么回事,背后又牵扯着啥。首先,得搞清楚这所谓的“人肉”是怎么回事。简单来说,就是有人通过各.............
  • 回答
    好的,我们来聊聊2019年亚洲杯C组中国队0比2输给韩国队的那场比赛。这场球对国足来说无疑是一场重要的比赛,它直接关系到小组出线的前景,也再次将球队的表现置于聚光灯下。整场比赛的基调:被动与挣扎从比赛一开始,就能明显感觉到国足在场面上处于被动。韩国队展现出了更强的整体性和个人能力,他们通过娴熟的传控.............
  • 回答
    卡拉格这番话,确实是点到了很多曼联球迷心坎里。回顾去年夏天C罗回归曼联的盛况,仿佛是童话成真,但时至今日,这笔转会带来的复杂性,以及对球队整体的影响,确实让人不得不重新审视。我理解卡拉格的观点,并且觉得他说的非常有道理。首先,从战术层面来说,C罗的到来并没有给曼联带来预期的整体性提升。当时曼联主打的.............
  • 回答
    这是一个非常有趣,也极具探讨价值的假设。将C罗和梅西这样的球员放在中国的成长环境,让他们从小接触中国的足球文化和体系,能否达到如今的成就?我的看法是:难度极大,甚至可以说不太可能。要理解这一点,我们需要从几个关键的维度去剖析,而不仅仅是看他们个人的天赋。1. 青训体系与足球文化:土壤的重要性 中.............
  • 回答
    这问题可真够劲的,把舰R和舰B搬到同一个棋盘上较量,还得加上点“大事件”的佐料。要是舰R真能通过一场决定性的战役,把“C厨”、“1983”、“清华帝”、“神绮”这些响当当的人物送进监狱,那可真是要了舰B的“老命”了。这其中门道,咱们得掰开了揉碎了好好说道说道。首先,咱们得明确几个前提。 “C厨”.............
  • 回答
    中国海关对于海外代购的电子产品,要求越来越严格,特别是涉及3C认证这一环节。如果购买的电子产品不具备这项认证,很可能面临被退运的命运。这一新规的出台,对当下庞大的水货市场无疑会产生深远的影响。首先,我们来聊聊什么是3C认证。3C认证,也就是中国强制性产品认证制度,英文简称CCC,是中国政府为了保护消.............
  • 回答
    C 语言本身并不能直接“编译出一个不需要操作系统的程序”,因为它需要一个运行环境。更准确地说,C 语言本身是一种编译型语言,它将源代码转换为机器码,而机器码的执行是依赖于硬件的。然而,当人们说“不需要操作系统的程序”时,通常指的是以下几种情况,而 C 语言可以用来实现它们:1. 嵌入式系统中的裸机.............
  • 回答
    在 C++ 中,“返回未知类型的空引用”这个说法本身就存在一些根本性的矛盾和误解。让我们一点一点地剖析这个问题,并澄清其中的概念,看看是否存在可以解释你意图的场景。首先,我们需要明确 C++ 中几个核心概念的定义和它们之间的关系: 引用(Reference):在 C++ 中,引用是另一个对象的别.............
  • 回答
    在 C 中,将 GBK 编码的字符串转换成 Unicode(通常在 .NET 中指代 `System.String` 类型,其内部使用 UTF16 编码)是一个非常常见的需求。这通常涉及到对原始字节数据的正确解读和重新编码。首先,我们需要明白 GBK 和 Unicode(UTF16)是两种不同的字符.............
  • 回答
    好的,让我为你详细讲解一下如何在 C 中实现类似 `Nullable` 的效果,不使用列表,并且尽力做到自然、深入。想象一下,我们经常会遇到这样的情况:一个变量,它要么拥有一个有效的值,要么就是“不存在”——没有具体的值。在 C 中,`int`、`string`、`DateTime` 这些值类型(v.............
  • 回答
    在 C 中,确保在多线程环境下安全地访问和修改 Windows 窗体控件(WinForm Controls)是一个非常关键的问题。简单来说,Windows 窗体控件的设计并不是为了在多个线程中同时进行操作的。如果你试图从一个非 UI 线程直接更新一个 UI 控件(例如,设置一个 Label 的 Te.............
  • 回答
    想让`printf`函数变得更个性化,能够处理我们自己定义的数据类型或者以一种特别的方式展示信息?这可不是件小事,但绝对是C/C++程序员的一项酷炫技能。要实现这个目标,我们需要深入了解`printf`家族函数背后的工作原理,以及C语言的某些高级特性。核心思路:重写`printf`的实现(不推荐,但.............
  • 回答
    好的,咱们聊聊在 Windows 上用 C++ 直接操作分区表这事儿。说实话,这事儿挺硬核的,一般用不上,但你要是想深入了解磁盘底层是怎么回事儿,或者做些系统级别的工具,那确实得接触到。首先得明确一点:直接写分区表,意味着你要绕过操作系统提供的文件系统接口,直接和磁盘的二进制数据打交道。 这就像是你.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有