49.网络通信-超文本传输HTTP-下载数据
49.1 知识点
Head请求类型检测资源可用性
利用 Head 请求类型,获取信息
try
{
// 尝试执行以下操作,捕获可能的异常
// 在这里,我们尝试获取远程服务器上文件的信息
// 1. 创建 HTTP 通讯用连接对象 HttpWebRequest 对象
HttpWebRequest httpWebRequest = HttpWebRequest.Create(new Uri("http://192.168.1.101:8000/HTTPRoot/pic.png")) as HttpWebRequest;
// 2. 设置请求类型或其他相关参数
httpWebRequest.Method = WebRequestMethods.Http.Head; // 使用 HTTP HEAD 请求方法
httpWebRequest.Timeout = 2000; // 设置请求超时时间为 2 秒
// 3. 发送请求,获取响应结果 HttpWebResponse 对象
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 检查响应的状态码
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 如果状态码为 200 (OK),表示文件存在且可用
print("文件存在且可用");
print(httpWebResponse.ContentLength); // 打印文件大小
print(httpWebResponse.ContentType); // 打印文件的 MIME 类型
httpWebResponse.Close(); // 关闭响应对象,释放资源
}
else
{
// 如果状态码不是 200,文件不能用,打印状态码
print("文件不能用" + httpWebResponse.StatusCode);
}
}
catch (WebException w)
{
// 捕获 WebException 异常,通常表示网络请求出错
print("获取出错" + w.Message + w.Status); // 打印错误消息和状态信息
}
Get请求类型下载资源
利用 Get 请求类型,下载资源
try
{
// 尝试执行以下操作,捕获可能的异常
// 在这里,我们尝试下载远程文件到本地
// 1. 创建 HTTP 通讯用连接对象 HttpWebRequest 对象
HttpWebRequest httpWebRequest = HttpWebRequest.Create(new Uri("http://192.168.1.101:8000/HTTPRoot/pic.png")) as HttpWebRequest;
// 2. 设置请求类型或其他相关参数
httpWebRequest.Method = WebRequestMethods.Http.Get; // 使用 HTTP GET 请求方法
httpWebRequest.Timeout = 3000; // 设置请求超时时间为 3 秒
// 3. 发送请求,获取响应结果 HttpWebResponse 对象
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 4. 获取响应数据流,写入本地路径
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 打印本地数据存储路径
print("本地存储路径:" + Application.persistentDataPath);
// 创建本地文件流以将下载的数据写入本地
using (FileStream fileStream = File.Create(Application.persistentDataPath + "/httpPic.png"))
{
Stream downloadResponseStream = httpWebResponse.GetResponseStream();
byte[] bytes = new byte[2048];
// 读取数据
int contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
// 一点一点地写入本地
while (contentLength != 0)
{
fileStream.Write(bytes, 0, contentLength);
contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
}
fileStream.Close();
downloadResponseStream.Close();
httpWebResponse.Close();
}
// 打印下载成功消息
print("下载成功");
}
else
{
// 如果状态码不是 200 (OK),下载失败,打印状态码
print("下载失败,状态码:" + httpWebResponse.StatusCode);
}
}
catch (WebException w)
{
// 捕获 WebException 异常,通常表示网络请求出错
print("下载出错,状态:" + w.Status + ",错误消息:" + w.Message);
}
测试结果
Get 请求类型携带额外信息
我们在进行 HTTP 通信时,可以在地址后面加一些额外参数传递给服务端。一般在和短连接游戏服务器通讯时,需要携带额外信息。
举例:
这个链接可以分成几部分:
协议部分:取决于服务器端使用的哪种协议
- http:// —— 普通的 HTTP 超文本传输协议
- https:// —— 加密的超文本传输协议
域名部分:
- www.aspxfans.com
- 也可以填写服务器的公网 IP 地址
端口部分:
- 8080
- 可以不写,如果不写默认为 80
虚拟目录部分:
- news/child/
- 域名后的 / 开始,到最后一个 / 之前的部分
文件名部分:
- index.asp
- ?之前的最后一个 / 后的部分
参数部分:
- boardID=5&ID=24618&page=1
- ?之后的部分就是参数部分,多个参数一 & 分隔开
- 这里有三个参数
- boardID = 5
- ID = 24618
- page = 1
我们在和服务端进行通信时,只要按照这种规则格式进行通信,就可以传递参数给对象。主要可用于:
- web 网站服务器
- 游戏短连接服务器
- 等
总结
Head 请求类型
- 主要用于获取文件的一些基础信息,可以用于确定文件是否存在。
Get 请求类型
- 主要用于传递信息给服务器,用于获取具体信息。
- 服务器返回的信息,可以通过 Response 中的流来获取。
- 用 Get 请求时,可以在连接中携带一些额外参数(在链接后面加上 ? 参数名=参数值&参数名=参数值&参数名=参数值&…)。
- 正常的 HTTP 服务器应用程序,都会去解析 Get 请求时连接中的参数进行逻辑处理(后端程序的工作)。
- 我们主要要掌握的知识点:
- 额外参数按格式书写
- 通过 Response 对象中的流来获取返回的数据(数据的类型多种多样,可以是文件、自定义消息等等,我们按照规则解析即可)。
在和 HTTP 服务器通信时,我们经常会使用额外参数的形式传递信息,特别是以后和一些运营平台对接时。
文件下载功能和 Ftp 非常类似,只是其中使用的类、协议、请求类型不同而已。
49.2 知识点代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
public class Lesson49_网络通信_超文本传输HTTP_下载数据 : MonoBehaviour
{
void Start()
{
#region 知识点一 检测资源可用性
//利用Head请求类型,获取信息
try
{
// 尝试执行以下操作,捕获可能的异常
// 在这里,我们尝试获取远程服务器上文件的信息
// 1. 创建HTTP通讯用连接对象HttpWebRequest对象
HttpWebRequest httpWebRequest = HttpWebRequest.Create(new Uri("http://192.168.1.101:8000/HTTPRoot/pic.png")) as HttpWebRequest;
// 2. 设置请求类型或其他相关参数
httpWebRequest.Method = WebRequestMethods.Http.Head; // 使用HTTP HEAD请求方法
httpWebRequest.Timeout = 2000; // 设置请求超时时间为2秒
// 3. 发送请求,获取响应结果HttpWebResponse对象
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 检查响应的状态码
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 如果状态码为200 (OK),表示文件存在且可用
print("文件存在且可用");
print(httpWebResponse.ContentLength); // 打印文件大小
print(httpWebResponse.ContentType); // 打印文件的MIME类型
httpWebResponse.Close(); // 关闭响应对象,释放资源
}
else
{
// 如果状态码不是200,文件不能用,打印状态码
print("文件不能用" + httpWebResponse.StatusCode);
}
}
catch (WebException w)
{
// 捕获WebException异常,通常表示网络请求出错
print("获取出错" + w.Message + w.Status); // 打印错误消息和状态信息
}
#endregion
#region 知识点二 下载资源
//利用Get请求类型,下载资源
try
{
// 尝试执行以下操作,捕获可能的异常
// 在这里,我们尝试下载远程文件到本地
// 1. 创建HTTP通讯用连接对象HttpWebRequest对象
HttpWebRequest httpWebRequest = HttpWebRequest.Create(new Uri("http://192.168.1.101:8000/HTTPRoot/pic.png")) as HttpWebRequest;
// 2. 设置请求类型或其他相关参数
httpWebRequest.Method = WebRequestMethods.Http.Get; // 使用HTTP GET请求方法
httpWebRequest.Timeout = 3000; // 设置请求超时时间为3秒
// 3. 发送请求,获取响应结果HttpWebResponse对象
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 4. 获取响应数据流,写入本地路径
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 打印本地数据存储路径
print("本地存储路径:" + Application.persistentDataPath);
// 创建本地文件流以将下载的数据写入本地
using (FileStream fileStream = File.Create(Application.persistentDataPath + "/httpPic.png"))
{
Stream downloadResponseStream = httpWebResponse.GetResponseStream();
byte[] bytes = new byte[2048];
// 读取数据
int contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
// 一点一点地写入本地
while (contentLength != 0)
{
fileStream.Write(bytes, 0, contentLength);
contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
}
fileStream.Close();
downloadResponseStream.Close();
httpWebResponse.Close();
}
// 打印下载成功消息
print("下载成功");
}
else
{
// 如果状态码不是200 (OK),下载失败,打印状态码
print("下载失败,状态码:" + httpWebResponse.StatusCode);
}
}
catch (WebException w)
{
// 捕获WebException异常,通常表示网络请求出错
print("下载出错,状态:" + w.Status + ",错误消息:" + w.Message);
}
#endregion
#region 知识点三 Get请求类型携带额外信息
//我们在进行HTTP通信时,可以在地址后面加一些额外参数传递给服务端
//一般在和短连接游戏服务器通讯时,需要携带额外信息
//举例:
//http://www.aspxfans.com:8080/news/child/index.asp?boardID=5&ID=24618&page=1
//这个链接可以分成几部分
//1.协议部分:取决于服务器端使用的哪种协议
//http:// —— 普通的http超文本传输协议
//https:// —— 加密的超文本传输协议
//2.域名部分:
//www.aspxfans.com
//也可以填写服务器的公网IP地址
//3.端口部分:
//8080
//可以不写,如果不写默认为80
//4.虚拟目录部分:
//news/child/
//域名后的/开始,到最后一个/之前的部分
//5.文件名部分:
//index.asp
//?之前的最后一个/后的部分
//6.参数部分:
//boardID=5&ID=24618&page=1
//?之后的部分就是参数部分,多个参数一&分隔开
//这里有三个参数
//boardID = 5
//ID = 24618
//page = 1
//我们在和服务端进行通信时,只要按照这种规则格式进行通信,就可以传递参数给对象
//主要可用于:
//1.web网站服务器
//2.游戏短连接服务器
//等
#endregion
#region 总结
//1.Head请求类型
//主要用于获取文件的一些基础信息 可以用于确定文件是否存在
//2.Get请求类型 主要用于传递信息给服务器,用于获取具体信息
// 服务器返回的信息,可以通过Response中的流来获取
// 用Get请求时,可以在连接中携带一些额外参数(在链接后面加上 ?参数名=参数值&参数名=参数值&参数名=参数值&。。。。)
// 正常的http服务器应用程序,都会去解析Get请求时连接中的参数进行逻辑处理(后端程序的工作)
// 我们主要要掌握的知识点:
// 1.额外参数按格式书写
// 2.通过response对象中的流来获取返回的数据(数据的类型多种多样,可以是文件、自定义消息等等,我们按照规则解析即可)
//3.在和http服务器通信时,我们经常会使用额外参数的形式传递信息,特别是以后和一些运营平台对接时
//4.文件下载功能和Ftp非常类似,只是其中使用的类、协议、请求类型不同而已
#endregion
}
}
49.3 练习题
实现一个Http管理器,将下载方法封装在其中,用多线程的形式处理下载,避免影响主线程逻辑
创建HttpManager管理器,继承C#单例,定义服务器路径
public class HttpManager : BaseSingletonInCSharp<HttpManager>
{
private string HTTP_PATH = "http://192.168.1.101:8000/HTTPRoot/";
}
定义下载指定文件到本地指定路径中的方法,先用Head判断文件是否存在,存在在用Get获取
/// <summary>
/// 下载指定文件到本地指定路径中
/// </summary>
/// <param name="fileName">远程文件名</param>
/// <param name="loacFilePath">本地路径</param>
/// <param name="action">下载结束后的回调函数</param>
public async void DownLoadFile(string fileName, string loacFilePath, UnityAction<HttpStatusCode> action)
{
// 创建一个临时变量,用于存储HTTP响应的状态码,默认为OK。
HttpStatusCode httpStatusCodeResult = HttpStatusCode.OK;
// 使用异步任务来执行下载操作,以避免阻塞主线程。
await Task.Run(() =>
{
try
{
// 判断文件是否存在 Head
// 1. 创建HTTP连接对象,用于发送HTTP请求到服务器。
HttpWebRequest httpWebRequest = HttpWebRequest.Create(HTTP_PATH + fileName) as HttpWebRequest;
// 2. 设置请求类型为HEAD,这样我们可以检查文件是否存在,以及设置其他相关参数。
httpWebRequest.Method = WebRequestMethods.Http.Head;
httpWebRequest.Timeout = 2000;
// 3. 发送请求并获取HTTP响应。
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 如果文件存在才下载
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 关闭判断文件是否存在的请求。
httpWebResponse.Close();
// 下载文件 Get
// 1. 创建新的HTTP连接对象,用于下载文件。
httpWebRequest = HttpWebRequest.Create(HTTP_PATH + fileName) as HttpWebRequest;
// 2. 设置请求类型为GET,以获取文件内容,并设置其他相关参数。
httpWebRequest.Method = WebRequestMethods.Http.Get;
httpWebRequest.Timeout = 2000;
// 3. 发送请求并获取HTTP响应。
httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 4. 存储数据到本地
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 创建本地文件并准备将下载的数据写入其中。
using (FileStream fileStream = File.Create(loacFilePath))
{
// 获取HTTP响应的数据流,从中读取数据。
Stream downloadResponseStream = httpWebResponse.GetResponseStream();
// 创建一个字节数组,用于存储从数据流中读取的数据。
byte[] bytes = new byte[4096];
// 从数据流中读取一部分数据,并返回读取的字节数。
int contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
// 使用循环将数据写入本地文件,直到数据流读取完毕。
while (contentLength != 0)
{
fileStream.Write(bytes, 0, contentLength);
contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
}
// 关闭本地文件和数据流。
fileStream.Close();
downloadResponseStream.Close();
}
// 如果下载成功,将HTTP响应状态码设置为OK。
httpStatusCodeResult = HttpStatusCode.OK;
}
else
{
// 如果下载失败,将HTTP响应状态码存储在 httpStatusCodeResult 变量中。
httpStatusCodeResult = httpWebResponse.StatusCode;
}
}
else
{
// 如果文件不存在,将HTTP响应状态码存储在 httpStatusCodeResult 变量中。
httpStatusCodeResult = httpWebResponse.StatusCode;
}
// 关闭HTTP响应。
httpWebResponse.Close();
}
catch (WebException w)
{
// 如果发生Web异常,将状态码设置为服务器内部错误,并记录错误消息。
httpStatusCodeResult = HttpStatusCode.InternalServerError;
Debug.Log("下载出错" + w.Message + w.Status);
}
});
// 调用传递进来的 UnityAction 委托,将HTTP响应状态码传递给调用者。
action?.Invoke(httpStatusCodeResult);
}
测试下载服务器图片
print(Application.persistentDataPath);
HttpManager.Instance.DownLoadFile("pic.png", Application.persistentDataPath + "/httppic2.png", (code) =>
{
if (code == HttpStatusCode.OK)
print("下载成功");
else
print("下载失败" + code);
});
测试结果
49.4 练习题代码
HttpManager
using System.IO;
using System.Net;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
public class HttpManager : BaseSingletonInCSharp<HttpManager>
{
private string HTTP_PATH = "http://192.168.1.101:8000/HTTPRoot/";
/// <summary>
/// 下载指定文件到本地指定路径中
/// </summary>
/// <param name="fileName">远程文件名</param>
/// <param name="loacFilePath">本地路径</param>
/// <param name="action">下载结束后的回调函数</param>
public async void DownLoadFile(string fileName, string loacFilePath, UnityAction<HttpStatusCode> action)
{
// 创建一个临时变量,用于存储HTTP响应的状态码,默认为OK。
HttpStatusCode httpStatusCodeResult = HttpStatusCode.OK;
// 使用异步任务来执行下载操作,以避免阻塞主线程。
await Task.Run(() =>
{
try
{
// 判断文件是否存在 Head
// 1. 创建HTTP连接对象,用于发送HTTP请求到服务器。
HttpWebRequest httpWebRequest = HttpWebRequest.Create(HTTP_PATH + fileName) as HttpWebRequest;
// 2. 设置请求类型为HEAD,这样我们可以检查文件是否存在,以及设置其他相关参数。
httpWebRequest.Method = WebRequestMethods.Http.Head;
httpWebRequest.Timeout = 2000;
// 3. 发送请求并获取HTTP响应。
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 如果文件存在才下载
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 关闭判断文件是否存在的请求。
httpWebResponse.Close();
// 下载文件 Get
// 1. 创建新的HTTP连接对象,用于下载文件。
httpWebRequest = HttpWebRequest.Create(HTTP_PATH + fileName) as HttpWebRequest;
// 2. 设置请求类型为GET,以获取文件内容,并设置其他相关参数。
httpWebRequest.Method = WebRequestMethods.Http.Get;
httpWebRequest.Timeout = 2000;
// 3. 发送请求并获取HTTP响应。
httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
// 4. 存储数据到本地
if (httpWebResponse.StatusCode == HttpStatusCode.OK)
{
// 创建本地文件并准备将下载的数据写入其中。
using (FileStream fileStream = File.Create(loacFilePath))
{
// 获取HTTP响应的数据流,从中读取数据。
Stream downloadResponseStream = httpWebResponse.GetResponseStream();
// 创建一个字节数组,用于存储从数据流中读取的数据。
byte[] bytes = new byte[4096];
// 从数据流中读取一部分数据,并返回读取的字节数。
int contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
// 使用循环将数据写入本地文件,直到数据流读取完毕。
while (contentLength != 0)
{
fileStream.Write(bytes, 0, contentLength);
contentLength = downloadResponseStream.Read(bytes, 0, bytes.Length);
}
// 关闭本地文件和数据流。
fileStream.Close();
downloadResponseStream.Close();
}
// 如果下载成功,将HTTP响应状态码设置为OK。
httpStatusCodeResult = HttpStatusCode.OK;
}
else
{
// 如果下载失败,将HTTP响应状态码存储在 httpStatusCodeResult 变量中。
httpStatusCodeResult = httpWebResponse.StatusCode;
}
}
else
{
// 如果文件不存在,将HTTP响应状态码存储在 httpStatusCodeResult 变量中。
httpStatusCodeResult = httpWebResponse.StatusCode;
}
// 关闭HTTP响应。
httpWebResponse.Close();
}
catch (WebException w)
{
// 如果发生Web异常,将状态码设置为服务器内部错误,并记录错误消息。
httpStatusCodeResult = HttpStatusCode.InternalServerError;
Debug.Log("下载出错" + w.Message + w.Status);
}
});
// 调用传递进来的 UnityAction 委托,将HTTP响应状态码传递给调用者。
action?.Invoke(httpStatusCodeResult);
}
}
Lesson49_练习题
using System.Collections;
using System.Collections.Generic;
using System.Net;
using UnityEngine;
public class Lesson49_练习题 : MonoBehaviour
{
void Start()
{
print(Application.persistentDataPath);
HttpManager.Instance.DownLoadFile("pic.png", Application.persistentDataPath + "/httppic2.png", (code) =>
{
if (code == HttpStatusCode.OK)
print("下载成功");
else
print("下载失败" + code);
});
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com