【虚幻引擎】UE4 Http之异步请求数据

news2024/11/18 4:19:13

一、BlueprintAsyncActionBase

  UE提供了BlueprintAsyncActionBase类,实现异步加载的方式请求数据

虚幻的很多蓝图节点都采用了异步加载的方式

比如:延迟Delay,PlayMontage都是采用异步加载的方式进行实现

接下我们就用异步加载的方式实现HTTP请求下载

二、HTTP请求

新建一个C++项目,然后build.cs加入模块

		PrivateDependencyModuleNames.AddRange(new string[] { "HTTP", "Json" });

 创建继承自BlueprintAsyncActionBase的C++类

请求的Json格式的数据为

 代理声明:代理参数跟我们后面函数的输出参数有关,要想输出函数参数,需要在代理的位置声明返回参数

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRequestCompleteDelegate, const TArray<FNewsItem>&, Data,int32, ver);

 

 输出节点如OnSucceeded,OnFailed这些节点跟我们声明的代理有关,就是代理声明的对象

//输出节点
	UPROPERTY(BlueprintAssignable)
		FRequestCompleteDelegate OnSucceeded;

	//输出节点
	UPROPERTY(BlueprintAssignable)
		FRequestCompleteDelegate OnFailed;

 

 主要代码如下MyBlueprintAsyncActionBase.h文件

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Interfaces/IHttpRequest.h"
#include "MyBlueprintAsyncActionBase.generated.h"


USTRUCT(BlueprintType)
struct FNewsItem {
	GENERATED_USTRUCT_BODY()

		FNewsItem() {}
	FNewsItem(FString _Path, FString _Url)
		: Path(_Path), Url(_Url) {}
	UPROPERTY(BlueprintReadOnly)
		FString Path;
	UPROPERTY(BlueprintReadOnly)
		FString Url;
};

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRequestCompleteDelegate, const TArray<FNewsItem>&, Data,int32, ver);


/**
 * 
 */
UCLASS()
class TEST111_API UMyBlueprintAsyncActionBase : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
	
	UMyBlueprintAsyncActionBase();

	//json
public:

	// 自定义的异步蓝图节点
	UFUNCTION(BlueprintCallable, Category = "AsyncHttp", meta = (BlueprintInternalUseOnly = "true"))
		static UMyBlueprintAsyncActionBase* AsyncHttpURLRequest(const FString& url);

	void HttpRequestStar(const FString& url);
	void HttpRequest_RecHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful);

	//输出节点
	UPROPERTY(BlueprintAssignable)
		FRequestCompleteDelegate OnSucceeded;

	//输出节点
	UPROPERTY(BlueprintAssignable)
		FRequestCompleteDelegate OnFailed;


	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Version")
		int32 version;

};

MyBlueprintAsyncActionBase.cpp文件

// Fill out your copyright notice in the Description page of Project Settings.


#include "MyBlueprintAsyncActionBase.h"
#include "HttpModule.h"
#include "Interfaces/IHttpResponse.h"

UMyBlueprintAsyncActionBase::UMyBlueprintAsyncActionBase()
{
	if (HasAnyFlags(RF_ClassDefaultObject) == false)
	{
		AddToRoot(); //防止自动GC
	}
}

UMyBlueprintAsyncActionBase* UMyBlueprintAsyncActionBase::AsyncHttpURLRequest(const FString& url) {
	UMyBlueprintAsyncActionBase* AsyncHttpObject = NewObject<UMyBlueprintAsyncActionBase>();
	AsyncHttpObject->HttpRequestStar(url);
	return AsyncHttpObject;
}

//开始请求
void UMyBlueprintAsyncActionBase::HttpRequestStar(const FString& url)
{
	TSharedRef<IHttpRequest, ESPMode::ThreadSafe> request = FHttpModule::Get().CreateRequest();
	request->SetVerb("GET");
	request->SetURL(url);
	//request->SetHeader(TEXT("Content-Type"), TEXT("application/json;charset=utf-8"));
	//request->SetTimeout(200);
	//request->SetContentAsString(requestJsonStr); POST时候用
	//request->OnRequestProgress().BindUObject() 绑定进度
	request->OnProcessRequestComplete().BindUObject(this, &UMyBlueprintAsyncActionBase::HttpRequest_RecHandle); //请求回调
	request->ProcessRequest();
}
//请求回调
void UMyBlueprintAsyncActionBase::HttpRequest_RecHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful) {


	if (bWasSuccessful && response.IsValid() && EHttpResponseCodes::IsOk(response->GetResponseCode())) {
		TSharedPtr<FJsonObject> jsonObj;
		TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(response->GetContentAsString());

		if (FJsonSerializer::Deserialize(JsonReader, jsonObj)) {
			version = jsonObj->GetIntegerField("versionId");
			UE_LOG(LogTemp, Warning, TEXT("version is %d"), version);
			const TArray< TSharedPtr<FJsonValue> >* dataList;
			if (jsonObj->TryGetArrayField(TEXT("DataList"), dataList)) // 获取数组
			{
				TArray<FNewsItem> newsList;
				for (TSharedPtr<FJsonValue> item : *dataList)
				{
					TSharedPtr<FJsonObject>itemObjet = item->AsObject();

					newsList.Add(FNewsItem(
						itemObjet->GetStringField(TEXT("Path")),
						itemObjet->GetStringField(TEXT("Url"))
					));
				}
				OnSucceeded.Broadcast(newsList, version); // 成功的执行
				RemoveFromRoot();
				return;
			}
		}
	}
	OnFailed.Broadcast({},0); // 失败的执行
	RemoveFromRoot();
}

 

 

打开关卡蓝图:

 

 三、HTTP下载

这里我重新建了一个继承自BlueprintAsyncActionBase的类

TestBlueprintAsyncActionBase.h文件

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Interfaces/IHttpRequest.h"
#include "TestBlueprintAsyncActionBase.generated.h"


/**
 * 
 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FDownloadProgressDelegate1,
const int32&, ReceivedDataInBytes,
const int32&, TotalDataInBytes,
const TArray<uint8>&, BinaryData
);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDownloadDelegate1);

UCLASS()
class TEST111_API UTestBlueprintAsyncActionBase : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()

	UTestBlueprintAsyncActionBase();
public:
	//load data

	UFUNCTION(BlueprintCallable, Category = "MyAsyncHttp", meta = (BlueprintInternalUseOnly = "true"))
		static UTestBlueprintAsyncActionBase* AsyncHttpDownload(const FString& url);

	void DownloadRequestStart(const FString& url);
	void DownloadRequestHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful);
	void DownloadProgress(FHttpRequestPtr request, int32 bytesSent, int32 bytesReceived);

	//输出节点
	UPROPERTY(BlueprintAssignable)
		FDownloadProgressDelegate1 OnProgressUpdate; //最好把有参数的放在前面,不然参数在蓝图节点有时候被吃掉了

	//输出节点
	UPROPERTY(BlueprintAssignable)
		FDownloadDelegate1 Load_Ok;

	//输出节点
	UPROPERTY(BlueprintAssignable)
		FDownloadDelegate1 Load_Fail;
};

TestBlueprintAsyncActionBase.cpp文件 

// Fill out your copyright notice in the Description page of Project Settings.


#include "TestBlueprintAsyncActionBase.h"
#include "HttpModule.h"
#include "Interfaces/IHttpResponse.h"

UTestBlueprintAsyncActionBase::UTestBlueprintAsyncActionBase()
{
	if (HasAnyFlags(RF_ClassDefaultObject) == false)
	{
		AddToRoot(); //防止自动GC
	}
}

UTestBlueprintAsyncActionBase* UTestBlueprintAsyncActionBase::AsyncHttpDownload(const FString& url)
{
	UTestBlueprintAsyncActionBase* AsyncHttpObject = NewObject<UTestBlueprintAsyncActionBase>();
	AsyncHttpObject->DownloadRequestStart(url);
	return AsyncHttpObject;
}

void UTestBlueprintAsyncActionBase::DownloadRequestStart(const FString& url)
{
	TSharedRef<IHttpRequest, ESPMode::ThreadSafe> request = FHttpModule::Get().CreateRequest();
	request->SetVerb("GET");
	request->SetURL(url);
	request->OnProcessRequestComplete().BindUObject(this, &UTestBlueprintAsyncActionBase::DownloadRequestHandle); //请求回调
	request->OnRequestProgress().BindUObject(this, &UTestBlueprintAsyncActionBase::DownloadProgress);// 下载进度
	request->ProcessRequest();

	RemoveFromRoot(); // 手动GC
}

void UTestBlueprintAsyncActionBase::DownloadRequestHandle(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful)
{
	RemoveFromRoot();


	if (bWasSuccessful && response.IsValid() && EHttpResponseCodes::IsOk(response->GetResponseCode()))
	{
		if (response->GetContentLength() > 0) {
			TArray<uint8> EmptyData;
			OnProgressUpdate.Broadcast(response->GetContentLength(), response->GetContentLength(), EmptyData);
		}

		FString FileSavePath = FPaths::ProjectDir() + "/download/gameplay.png";
		FString Path, Filename, Extension;
		FPaths::Split(FileSavePath, Path, Filename, Extension);
		IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

		if (!PlatformFile.DirectoryExists(*Path))
		{
			if (!PlatformFile.CreateDirectoryTree(*Path))
			{
				UE_LOG(LogTemp, Error, TEXT("Create Directory Failed!"));
				Load_Fail.Broadcast();
				return;
			}
		}

		IFileHandle* FileHandle = PlatformFile.OpenWrite(*FileSavePath);
		if (FileHandle)
		{
			FileHandle->Write(response->GetContent().GetData(), response->GetContentLength());
			delete FileHandle;
			Load_Ok.Broadcast();
			return;
		}
		else {
			UE_LOG(LogTemp, Error, TEXT("Save File Failed!"));
			Load_Fail.Broadcast();
			return;
		}

	}
	UE_LOG(LogTemp, Error, TEXT("download File Failed!"));
	Load_Fail.Broadcast();
	return;
}

void UTestBlueprintAsyncActionBase::DownloadProgress(FHttpRequestPtr request, int32 bytesSent, int32 bytesReceived)
{
	if (request->GetResponse()->GetContentLength() > 0)
	{
		TArray<uint8> EmptyData;
		OnProgressUpdate.Broadcast(bytesReceived, request->GetResponse()->GetContentLength(), EmptyData);
	}
}


打开关卡蓝图设置:

 注意这里图片下载的位置在项目工程里新建了一个download的文件夹里面

FString FileSavePath = FPaths::ProjectDir() + "/download/gameplay.png";

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

类和对象3

继承 继承是三大面向对象特征之一&#xff0c;继承无处不在&#xff0c;继承不仅是代码复用&#xff0c;精髓之处在于用抽象思维编写代码&#xff0c;以达到程序更强的可扩展性。 //继承一个父类&#xff0c;只能继承非私有的数据&#xff08;属性和方法&#xff09; //prote…

大数据之Kafka基本知识和架构介绍

文章目录前言一、Kafka的基本介绍&#xff08;一&#xff09;Kafka的特点二、Kafka的架构总结前言 #博学谷IT学习技术支持# 本篇文章主要从Kafka的基本介绍&#xff0c;Kafka的架构入手&#xff0c;如果有不恰当或者有疑问的地方&#xff0c;非常欢迎各位的意见和建议&#xf…

jetson连接PCF8591读取模拟电压值

文章目录一.PCF8591介绍PCF8591引脚说明PCF8591设置地址二.PCF8591模块功能描述:主要性能指标:三.PCF8591模块接口说明三.PCF8591连接jetson nano四.jetson nano 获取PCF8591模块的输入输出python版本代码C版本代码一.PCF8591介绍 PCF8591是一个单片集成、 单独供电、 低功耗、…

【Linux】Linux编译器—gcc/g++的使用

目录一.背景二.gcc如何生成1.预处理&#xff08;进行宏替换&#xff09;2.编译(生成汇编)3.汇编(生成机器可识别代码)4.链接(生成可执行文件或库文件)三.函数库1.函数库的分类(1)动态库(2)静态库2.区别3.拓展四.记忆1.选项2.后缀五.gcc选项该篇博客需要使用vim编译器&#xff0…

excel排序技巧:这些不同方式的排序方法你都会了么

都说这Excel里暗藏玄机&#xff0c;求最大值的MAX函数可以用于查找&#xff0c;用于查找的LOOKUP函数可以对数据进行四舍五入…就连看似人人都会的Excel自动排序&#xff0c;也藏着许多我们不知道的“小秘密”。今天我们就来探索一下这些藏在自动排序中的“小秘密”。一、扩展选…

Numpy数据分析csv文件的应用

1.数据存取与函数 1.1.数据的CSV文件存取 CSV(Comma-Separated Value,逗号分隔值) CSV是一种常见的文件格式&#xff0c;用来存储批量数据 np.savetxt(frame, array, fmt‘%.18e’, delimiterNone) 复制代码 frame : 文件、字符串或产生器&#xff0c;可以是.gz或.bz2的压缩…

SpringCloud从入门到精通(七)

Gateway Gateway-概述 网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。 在微服务架构中&#xff0c;不同的微服务可以有不同的网络地址&#xff0c;各个微服务之间通过互相调用完成用户请求&#xff0c;客户端可能通过调用N个微服务的接口完成一个用户请求…

【C++】优先级队列、仿函数和反向迭代器

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;priority…

工具及方法 - 字幕下载网站

1&#xff0c;射手网&#xff08;伪&#xff09; 首页 - 射手网(伪) - assrt.net - 字幕下载&#xff0c;字幕组&#xff0c;中文字幕&#xff0c;美剧字幕&#xff0c;英剧字幕&#xff0c;双语字幕&#xff0c;新番字幕 2&#xff0c;国外网站。 Subscene - Passionate abo…

sentinel-热点参数限流

Pages 60 Sentinel 官方网站 OpenSergo 微服务治理 文档 Read Me新手指南Sentinel 介绍FAQRoadmap如何使用工作原理流量控制集群流控&#xff08;分布式流控&#xff09;网关流控熔断降级热点参数限流系统自适应限流黑白名单控制实时监控数据动态规则控制台生产环境使用 Sent…

【自学Python】Python IDLE使用

Python IDLE使用 Python IDLE使用教程 在 Windows 上安装好 Python 之后&#xff0c;Python 都会提供一个 Python 命令行工具&#xff0c;就叫 IDLE。IDLE 是一个 Python Shell&#xff0c;Python Shell 可以用于与 Python 进行交互。 Python IDLE使用 打开Python IDLE 首…

分布式基础篇4 —— 基础篇完结(谷粒商城)

分类维护一、三级分类后端实现准备工作跨域问题关闭 ESLint 检查前端实现二、分类删除前端完善分类列表后端实现——删除配置发送请求代码片段前端实现——删除三、分类增加前端实现四、分类修改五、拖拽菜单拖拽效果实现拖拽数据收集拖拽功能完成拖拽功能完善六、批量删除品牌…

粒子系统-常用子模块

目录 Emission &#xff08;发射&#xff09; Shape &#xff08;形状&#xff09; Cone &#xff08;锥形&#xff09; Velocity over Lifetime &#xff08;运动&#xff09; Limit Velocity over Lifetime (速度限制) Force over lifetime (受力) Color over Lifetim…

【C语言航路】第十站:指针进阶(二)

目录 六、函数指针数组 七、指向函数指针数组的指针 八、回调函数 1.回调函数的概念 2.回调函数实现计算器 3.回调函数实现冒泡排序 总结 六、函数指针数组 我们已经知道了函数指针&#xff0c;它的类型是int(*)(int,int)。那么我们能否进行推广呢&#xff1f;将其推广成…

基于AD Event日志实时检测DSRM后门

01、简介每个域控制器都有一个目录还原模式&#xff08;DSRM&#xff09;帐户&#xff0c;它的密码是在安装域控时设置的&#xff0c;实际上它对应的就是sam文件里的本地管理员“administrator”&#xff0c;基本很少会被重置&#xff0c;因此有着极强的隐蔽性。攻击者通过获取…

面试篇之NoSQL

面试篇之NoSQL一、redis持久化1.1、字节1.2、微软1.3、题解1.3.1、RDB快照1.3.2、AOF日志1.3.3、最佳实践二、redis删除策略2.1、字节2.2、阿里云2.3、题解2.3.1、过期删除2.3.2、内存淘汰2.3.3、LRU2.3.4、LFU三、redis高可用3.1、字节3.2、美团3.3、微软3.4、题解3.4.1、主从…

前端性能优化(六):传输加载优化

目录 一&#xff1a;启用压缩 Gzip 二&#xff1a;启用 Keep Alive 三&#xff1a;HTTP 资源缓存 3.1.HTTP 缓存方案 3.2.各大网站缓存策略参考 四&#xff1a;Service Worker 五&#xff1a;HTTP2 的性能提升 5.1.HTTP2 优势 5.2.开启 HTTP2 5.3.Server Push&#x…

【Spring(五)】带你深入了解bean的生命周期

1.5 bean的生命周期 bean的实例化已经说完了&#xff0c;我们最后再来讲讲bean的生命周期。 我们主要来围绕着bean生命周期控制来学习&#xff0c;那么什么是生命周期呢&#xff1f;其实就是一个东西从创建到消亡的完整过程&#xff0c;比如人从出生到死亡的整个过程&#xff…

【MySQL进阶】深入理解redoLog日志

【MySQL进阶】深入理解redoLog日志 文章目录【MySQL进阶】深入理解redoLog日志一&#xff1a;redo日志概述二&#xff1a;redo日志格式三&#xff1a;Mini-Transaction1&#xff1a;以组的形式写入redo日志2&#xff1a;Mini-Transaction的概念四&#xff1a;redo日志的写入过程…

富淼转债,优彩转债上市价格预测

富淼转债基本信息转债名称&#xff1a;富淼转债&#xff0c;评级&#xff1a;A&#xff0c;发行规模&#xff1a;4.5亿元。正股名称&#xff1a;富淼科技&#xff0c;今日收盘价&#xff1a;18.25&#xff0c;转股价格&#xff1a;20.26。当前转股价值 转债面值 / 转股价格 * …