55.网络通信-Unity网络类-UnityWebRequest类-常用上传数据
55.1 知识点
上传相关数据类
父接口IMultipartFormSection 数据相关类都继承该接口
//数据相关类都继承该接口
//我们可以用父类装子类
List<IMultipartFormSection> multipartFormSectionList = new List<IMultipartFormSection>();
子类MultipartFormDataSection 传键值对
//MultipartFormDataSection 一般用来传键值对
//1.二进制字节数组
multipartFormSectionList.Add(new MultipartFormDataSection(Encoding.UTF8.GetBytes("123123123123123")));
//2.字符串
multipartFormSectionList.Add(new MultipartFormDataSection("12312312312312312dsfasdf"));
//3.参数名,参数值(字节数组,字符串),编码类型,资源类型(常用)
multipartFormSectionList.Add(new MultipartFormDataSection("Name", "MrTao", Encoding.UTF8, "application/...."));
//4.参数名,字节数组,资源类型
multipartFormSectionList.Add(new MultipartFormDataSection("Msg", new byte[1024], "appl....."));
子类MultipartFormFileSection 传文件
//MultipartFormFileSection 一般用来传文件
//1.字节数组
multipartFormSectionList.Add(new MultipartFormFileSection(File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
//2.文件名,字节数组(常用)
multipartFormSectionList.Add(new MultipartFormFileSection("上传的文件.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
//3.字符串数据,文件名(常用)
multipartFormSectionList.Add(new MultipartFormFileSection("12312313212312", "test.txt"));
//4.字符串数据,编码格式,文件名(常用)
multipartFormSectionList.Add(new MultipartFormFileSection("12312313212312", Encoding.UTF8, "test.txt"));
//5.表单名,字节数组,文件名,文件类型
multipartFormSectionList.Add(new MultipartFormFileSection("file", new byte[1024], "test.txt", ""));
//6.表单名,字符串数据,编码格式,文件名
multipartFormSectionList.Add(new MultipartFormFileSection("file", "123123123", Encoding.UTF8, "test.txt"));
UnityWebRequest.Post上传相关
// 用于协同处理Post上传操作
IEnumerator UploadPost()
{
// 准备上传的数据的列表
List<IMultipartFormSection> multipartFormSectionList = new List<IMultipartFormSection>();
// 添加键值对相关的信息字段数据
// 添加名为 "Name" 的文本字段,值为 "MrTao"
multipartFormSectionList.Add(new MultipartFormDataSection("Name", "MrTao"));
// 创建一个 PlayerMessage 对象
PlayerMessage playerMessage = new PlayerMessage();
playerMessage.playerID = 1;
playerMessage.playerData = new PlayerData();
playerMessage.playerData.name = "MrTao";
playerMessage.playerData.atk = 6;
playerMessage.playerData.lev = 666;
// 添加名为 "playerMessage" 的文本字段,值为 PlayerMessage 对象的 JSON 字符串表示
multipartFormSectionList.Add(new MultipartFormDataSection("playerMessage", playerMessage.Writing()));
// 添加一些文件上传部分
// 添加名为 "TestTest123.png" 的二进制文件,内容为从指定路径读取的二进制数据
multipartFormSectionList.Add(new MultipartFormFileSection("TestTest123.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
// 添加名为 "123123123123123" 的文本文件,内容为 "Test123.txt" 文件的内容
multipartFormSectionList.Add(new MultipartFormFileSection("123123123123123", "Test123.txt"));
// 创建 UnityWebRequest 对象,将数据上传到指定的URL
UnityWebRequest unityWebRequest = UnityWebRequest.Post("http://192.168.1.101:8000/HTTPRoot/", multipartFormSectionList);
// 发送上传请求
unityWebRequest.SendWebRequest();
// 等待上传完成
while (!unityWebRequest.isDone)
{
// 打印上传进度和已上传的字节数
print(unityWebRequest.uploadProgress);
print(unityWebRequest.uploadedBytes);
yield return null;
}
// 打印最终上传进度和已上传的字节数
print(unityWebRequest.uploadProgress);
print(unityWebRequest.uploadedBytes);
// 检查上传是否成功
if (unityWebRequest.result == UnityWebRequest.Result.Success)
{
print("上传成功");
// 上传成功后,可以使用 unityWebRequest.downloadHandler.multipartFormSectionList 获取上传数据列表
}
else
{
// 上传失败时,打印错误信息、响应代码和结果
print("上传失败" + unityWebRequest.error + unityWebRequest.responseCode + unityWebRequest.result);
}
}
StartCoroutine(UploadPost());
UnityWebRequest.Put上传相关
// 用于协同处理Put上传操作
IEnumerator UploadPut()
{
// 创建 UnityWebRequest 对象,使用 HTTP PUT 方法上传文件
// 指定要上传的URL和要上传的文件内容,这里使用了 UnityWebRequest.Put 方法 要后端配合
UnityWebRequest unityWebRequest = UnityWebRequest.Put("http://192.168.1.101:8000/HTTPRoot/", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png"));
// 发送上传请求并等待完成
yield return unityWebRequest.SendWebRequest();
// 检查上传是否成功
if (unityWebRequest.result == UnityWebRequest.Result.Success)
{
print("Put 上传成功");
}
else
{
// 在上传失败时可以添加错误处理逻辑
// 例如,可以通过 unityWebRequest.error 访问错误消息,以便进行错误处理
}
}
// 注意:Put请求类型不是所有的web服务器都认,必须要服务器处理该请求类型那么才能有相应
StartCoroutine(UploadPut());
总结
我们可以利用Post上传数据或上传文件
Put主要用于上传文件,但是必须资源服务器支持Put请求类型
为了通用性,我们可以统一使用Post请求类型进行数据和资源的上传
它的使用和之前的WWW类似,只要前后端制定好规则就可以相互通信了
55.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class Lesson55_网络通信_Unity网络类_UnityWebRequest类_常用上传数据 : MonoBehaviour
{
void Start()
{
#region 知识点一 上传相关数据类
//数据父接口 IMultipartFormSection
//数据相关类都继承该接口
//我们可以用父类装子类
List<IMultipartFormSection> multipartFormSectionList = new List<IMultipartFormSection>();
//数据子类
//MultipartFormDataSection 一般用来传键值对
//1.二进制字节数组
multipartFormSectionList.Add(new MultipartFormDataSection(Encoding.UTF8.GetBytes("123123123123123")));
//2.字符串
multipartFormSectionList.Add(new MultipartFormDataSection("12312312312312312dsfasdf"));
//3.参数名,参数值(字节数组,字符串),编码类型,资源类型(常用)
multipartFormSectionList.Add(new MultipartFormDataSection("Name", "MrTao", Encoding.UTF8, "application/...."));
//4.参数名,字节数组,资源类型
multipartFormSectionList.Add(new MultipartFormDataSection("Msg", new byte[1024], "appl....."));
//MultipartFormFileSection 一般用来传文件
//1.字节数组
multipartFormSectionList.Add(new MultipartFormFileSection(File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
//2.文件名,字节数组(常用)
multipartFormSectionList.Add(new MultipartFormFileSection("上传的文件.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
//3.字符串数据,文件名(常用)
multipartFormSectionList.Add(new MultipartFormFileSection("12312313212312", "test.txt"));
//4.字符串数据,编码格式,文件名(常用)
multipartFormSectionList.Add(new MultipartFormFileSection("12312313212312", Encoding.UTF8, "test.txt"));
//5.表单名,字节数组,文件名,文件类型
multipartFormSectionList.Add(new MultipartFormFileSection("file", new byte[1024], "test.txt", ""));
//6.表单名,字符串数据,编码格式,文件名
multipartFormSectionList.Add(new MultipartFormFileSection("file", "123123123", Encoding.UTF8, "test.txt"));
#endregion
#region 知识点二 Post发送相关
StartCoroutine(UploadPost());
#endregion
#region 知识点三 Put上传相关
//注意:Put请求类型不是所有的web服务器都认,必须要服务器处理该请求类型那么才能有相应
StartCoroutine(UploadPut());
#endregion
#region 总结
//我们可以利用Post上传数据或上传文件
//Put主要用于上传文件,但是必须资源服务器支持Put请求类型
//为了通用性,我们可以统一使用Post请求类型进行数据和资源的上传
//它的使用和之前的WWW类似,只要前后端制定好规则就可以相互通信了
#endregion
}
#region 知识点二 Post发送相关
// 用于协同处理Post上传操作
IEnumerator UploadPost()
{
// 准备上传的数据的列表
List<IMultipartFormSection> multipartFormSectionList = new List<IMultipartFormSection>();
// 添加键值对相关的信息字段数据
// 添加名为 "Name" 的文本字段,值为 "MrTao"
multipartFormSectionList.Add(new MultipartFormDataSection("Name", "MrTao"));
// 创建一个 PlayerMessage 对象
PlayerMessage playerMessage = new PlayerMessage();
playerMessage.playerID = 1;
playerMessage.playerData = new PlayerData();
playerMessage.playerData.name = "MrTao";
playerMessage.playerData.atk = 6;
playerMessage.playerData.lev = 666;
// 添加名为 "playerMessage" 的文本字段,值为 PlayerMessage 对象的 JSON 字符串表示
multipartFormSectionList.Add(new MultipartFormDataSection("playerMessage", playerMessage.Writing()));
// 添加一些文件上传部分
// 添加名为 "TestTest123.png" 的二进制文件,内容为从指定路径读取的二进制数据
multipartFormSectionList.Add(new MultipartFormFileSection("TestTest123.png", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png")));
// 添加名为 "123123123123123" 的文本文件,内容为 "Test123.txt" 文件的内容
multipartFormSectionList.Add(new MultipartFormFileSection("123123123123123", "Test123.txt"));
// 创建 UnityWebRequest 对象,将数据上传到指定的URL
UnityWebRequest unityWebRequest = UnityWebRequest.Post("http://192.168.1.101:8000/HTTPRoot/", multipartFormSectionList);
// 发送上传请求
unityWebRequest.SendWebRequest();
// 等待上传完成
while (!unityWebRequest.isDone)
{
// 打印上传进度和已上传的字节数
print(unityWebRequest.uploadProgress);
print(unityWebRequest.uploadedBytes);
yield return null;
}
// 打印最终上传进度和已上传的字节数
print(unityWebRequest.uploadProgress);
print(unityWebRequest.uploadedBytes);
// 检查上传是否成功
if (unityWebRequest.result == UnityWebRequest.Result.Success)
{
print("上传成功");
// 上传成功后,可以使用 unityWebRequest.downloadHandler.multipartFormSectionList 获取上传数据列表
}
else
{
// 上传失败时,打印错误信息、响应代码和结果
print("上传失败" + unityWebRequest.error + unityWebRequest.responseCode + unityWebRequest.result);
}
}
#endregion
#region 知识点三 Put上传相关
// 用于协同处理Put上传操作
IEnumerator UploadPut()
{
// 创建 UnityWebRequest 对象,使用 HTTP PUT 方法上传文件
// 指定要上传的URL和要上传的文件内容,这里使用了 UnityWebRequest.Put 方法 要后端配合
UnityWebRequest unityWebRequest = UnityWebRequest.Put("http://192.168.1.101:8000/HTTPRoot/", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png"));
// 发送上传请求并等待完成
yield return unityWebRequest.SendWebRequest();
// 检查上传是否成功
if (unityWebRequest.result == UnityWebRequest.Result.Success)
{
print("Put 上传成功");
}
else
{
// 在上传失败时可以添加错误处理逻辑
// 例如,可以通过 unityWebRequest.error 访问错误消息,以便进行错误处理
}
}
#endregion
}
55.3 练习题
请在一个NetWWW管理类当中,封装一个基于UnityWebRequest上传文件的方法
在NetWWW管理器中封装异步用UnityWebRequest上传的方法
/// <summary>
/// 上传文件的方法
/// </summary>
/// <param name="fileName">上传上去的文件名</param>
/// <param name="localPath">本地想要上传文件的路径</param>
/// <param name="action">上传完成后的回调函数</param>
public void UploadFile(string fileName, string localPath, UnityAction<UnityWebRequest.Result> action)
{
StartCoroutine(UploadFileAsync(fileName, localPath, action));
}
/// <summary>
/// 异步上传文件的方法
/// </summary>
/// <param name="fileName">上传上去的文件名</param>
/// <param name="localPath">本地想要上传文件的路径</param>
/// <param name="action">上传完成后的回调函数</param>
/// <returns></returns>
private IEnumerator UploadFileAsync(string fileName, string localPath, UnityAction<UnityWebRequest.Result> action)
{
// 创建一个列表来存储上传文件的数据
List<IMultipartFormSection> multipartFormSectionList = new List<IMultipartFormSection>();
// 向列表中添加要上传的文件,包括文件名和文件的二进制数据
multipartFormSectionList.Add(new MultipartFormFileSection(fileName, File.ReadAllBytes(localPath)));
// 创建一个UnityWebRequest对象,用于执行文件上传
UnityWebRequest unityWebRequest = UnityWebRequest.Post(HTTP_SERVER_PATH, multipartFormSectionList);
// 发送上传请求并等待完成
yield return unityWebRequest.SendWebRequest();
// 调用回调函数,传递上传结果
action?.Invoke(unityWebRequest.result);
// 如果上传不成功
if (unityWebRequest.result != UnityWebRequest.Result.Success)
{
// 输出警告信息,包括错误消息和响应代码
Debug.LogWarning("上传出现问题" + unityWebRequest.error + unityWebRequest.responseCode);
}
}
进行测试
NetWWWManager.Instance.UploadFile("练习题上传UnityWebRequest.png", Application.streamingAssetsPath + "/test.png", (code) =>
{
if (code == UnityWebRequest.Result.Success)
{
print("上传成功");
}
else
print("上传失败" + code);
});
55.4 练习题代码
NetWWWManager
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
public class NetWWWManager : BaseSingletonInMonoBehaviour<NetWWWManager>
{
private string HTTP_SERVER_PATH = "http://192.168.1.101:8000/HTTPRoot/";
/// <summary>
/// 提供给外部加载资源用的方法
/// </summary>
/// <typeparam name="T">资源的类型</typeparam>
/// <param name="path">资源的路径 http ftp file都支持</param>
/// <param name="action">加载结束后的回调函数 因为WWW是通过结合协同程序异步加载的 所以不能马上获取结果 需要回调获取</param>
public void LoadResource<T>(string path, UnityAction<T> action) where T : class
{
StartCoroutine(LoadResourceAsync<T>(path, action));
}
/// <summary>
/// 内部异步使用WWW加载资源用的协程方法
/// </summary>
/// <typeparam name="T">资源的类型</typeparam>
/// <param name="path">资源的路径 http ftp file都支持</param>
/// <param name="action">加载结束后的回调函数 因为WWW是通过结合协同程序异步加载的 所以不能马上获取结果 需要回调获取</param>
private IEnumerator LoadResourceAsync<T>(string path, UnityAction<T> action) where T : class
{
//声明www对象 用于下载或加载
WWW www = new WWW(path);
//等待下载或者加载结束(异步)
yield return www;
//优化的话可以让外部多传一个在加载时逻辑处理的委托回调
//如果没有错误 证明加载成功
if (www.error == null)
{
//根据T泛型的类型 决定使用哪种类型的资源 传递给外部
if (typeof(T) == typeof(AssetBundle))
{
action?.Invoke(www.assetBundle as T);
}
else if (typeof(T) == typeof(Texture))
{
action?.Invoke(www.texture as T);
}
else if (typeof(T) == typeof(AudioClip))
{
action?.Invoke(www.GetAudioClip() as T);
}
else if (typeof(T) == typeof(string))
{
action?.Invoke(www.text as T);
}
else if (typeof(T) == typeof(byte[]))
{
action?.Invoke(www.bytes as T);
}
//自定义一些类型 可能需要将bytes 转换成对应的类型来使用
}
//如果错误 就提示别人
else
{
//优化的话可以让外部多传一个在错误时委托回调
Debug.LogError("www加载资源出错" + www.error);
}
}
/// <summary>
/// 发送消息的通用方法,通过协程异步发送消息并在接收响应后执行指定的动作。
/// </summary>
/// <typeparam name="T">消息类型的泛型参数,必须是BaseMsg的派生类。</typeparam>
/// <param name="baseMessage">要发送的消息对象。</param>
/// <param name="action">消息发送成功后要执行的动作。</param>
public void SendMessage<T>(BaseMessage baseMessage, UnityAction<T> action) where T : BaseMessage
{
// 启动协程异步发送消息
StartCoroutine(SendMessageAsync<T>(baseMessage, action));
}
/// <summary>
/// 通过协程异步发送消息,并等待响应。
/// </summary>
/// <typeparam name="T">消息类型的泛型参数,必须是BaseMsg的派生类。</typeparam>
/// <param name="BaseMessage">要发送的消息对象。</param>
/// <param name="action">消息发送成功后要执行的动作。</param>
private IEnumerator SendMessageAsync<T>(BaseMessage BaseMessage, UnityAction<T> action) where T : BaseMessage
{
// 创建一个WWWForm来准备要发送的消息数据
WWWForm wWWForm = new WWWForm();
// 将消息数据以二进制形式添加到WWWForm中
wWWForm.AddBinaryData("BaseMessage", BaseMessage.Writing());
// 创建一个WWW对象并发送消息到HTTP服务器
WWW www = new WWW(HTTP_SERVER_PATH, wWWForm);
// 等待异步操作完成,即等待消息发送结束
yield return www;
// 检查是否有错误发生
if (www.error == null)
{
// 解析从服务器返回的消息,提取消息ID和消息长度
int index = 0;
int msgID = BitConverter.ToInt32(www.bytes, index);
index += 4;
int msgLength = BitConverter.ToInt32(www.bytes, index);
index += 4;
// 根据消息ID反序列化消息
BaseMessage baseMessage = null;
switch (msgID)
{
case 1001:
baseMessage = new PlayerMessage();
baseMessage.Reading(www.bytes, index);
break;
}
// 调用指定的动作,并将反序列化后的消息作为泛型参数传递
if (baseMessage != null)
action?.Invoke(baseMessage as T);
}
else
{
// 输出错误信息
Debug.LogError("发消息出问题" + www.error);
}
}
/// <summary>
/// 上传文件的方法
/// </summary>
/// <param name="fileName">上传上去的文件名</param>
/// <param name="localPath">本地想要上传文件的路径</param>
/// <param name="action">上传完成后的回调函数</param>
public void UploadFile(string fileName, string localPath, UnityAction<UnityWebRequest.Result> action)
{
StartCoroutine(UploadFileAsync(fileName, localPath, action));
}
/// <summary>
/// 异步上传文件的方法
/// </summary>
/// <param name="fileName">上传上去的文件名</param>
/// <param name="localPath">本地想要上传文件的路径</param>
/// <param name="action">上传完成后的回调函数</param>
/// <returns></returns>
private IEnumerator UploadFileAsync(string fileName, string localPath, UnityAction<UnityWebRequest.Result> action)
{
// 创建一个列表来存储上传文件的数据
List<IMultipartFormSection> multipartFormSectionList = new List<IMultipartFormSection>();
// 向列表中添加要上传的文件,包括文件名和文件的二进制数据
multipartFormSectionList.Add(new MultipartFormFileSection(fileName, File.ReadAllBytes(localPath)));
// 创建一个UnityWebRequest对象,用于执行文件上传
UnityWebRequest unityWebRequest = UnityWebRequest.Post(HTTP_SERVER_PATH, multipartFormSectionList);
// 发送上传请求并等待完成
yield return unityWebRequest.SendWebRequest();
// 调用回调函数,传递上传结果
action?.Invoke(unityWebRequest.result);
// 如果上传不成功
if (unityWebRequest.result != UnityWebRequest.Result.Success)
{
// 输出警告信息,包括错误消息和响应代码
Debug.LogWarning("上传出现问题" + unityWebRequest.error + unityWebRequest.responseCode);
}
}
}
Lesson55_练习题
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class Lesson55_练习题 : MonoBehaviour
{
void Start()
{
NetWWWManager.Instance.UploadFile("练习题上传UnityWebRequest.png", Application.streamingAssetsPath + "/test.png", (code) =>
{
if (code == UnityWebRequest.Result.Success)
{
print("上传成功");
}
else
print("上传失败" + code);
});
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com