UE4笔记-C++使用Http网络请求下载JPG图片并创建生成UTexture2D纹理示例(jpg/png/HDR等)
备忘,C++做逻辑真是又臭又长👴
P.S:UE的Http模块相对简陋,可以集成cpr库模块,进行网络请求操作.
Note:例子没有生成Mipmap,如果用于游戏场景会有摩尔效应,生成Mipmap方法可参考:https://github.com/linqingwudiv1/QCorePlugin/blob/master/Source/QCorePlugin/Helper/ImageHelper.cpp
例子中的UCoreBPLibrary::UrlEncode函数可参考:
https://www.cnblogs.com/linqing/p/5321317.html
补充个示例用到的正则函数:
bool UCoreBPLibrary::RegexMatch(const FString& Str, const FString& Pattern, TArray<FString>& Result) { FRegexPattern MatherPatter(Pattern); FRegexMatcher Matcher(MatherPatter, Str); while (Matcher.FindNext()) { Result.Add(Matcher.GetCaptureGroup(0)); } return Result.Num() == 0 ? false : true; }
-------------------------------------------------------------------------------
使用示例:
因为我是放单例里用就没考虑回收的问题,可以继承下UObject.或用完手动回收一下..
Note:这里仅演示,存在内存泄漏
FDownloadImageHelper* helper = new FDownloadImageHelper (); helper->OnDownloadCompleted().AddLambda([&](bool isSuccessful, UTexture2D *t2d) { if (!isSuccessful) { return; } //your logic... this->t2d_basecolor = t2d; this->m_primaryMat->SetTextureParameterValue(FName{ TEXT("basecolor") }, t2d); }); helper->Start(TEXT("http://www.wakelu.com/test中文.png"));
主要依赖模块:
"HTTP", "Networking", "ImageWrapper"
HTTP封装类:
NetAPI.h
#pragma once
#include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Http.h" #include "NetAPI.generated.h" /** * */ UCLASS() class LQCOREPLUGIN_API UNetAPI : public UObject { GENERATED_BODY() public: //Setting.eg timeout/delay time/once read max buffer static FHttpModule* GetHttpModule(); static FHttpManager& GetHttpMgr(); //UFUNCTION() static TSharedRef<IHttpRequest> createRequst(FString _url, FString _method = TEXT("GET"), FString _content = TEXT(""), FString _contentType = TEXT("text/html;charset=UTF-8")); static TSharedRef<IHttpRequest> createUploadImageRequest(FString _url, TArray<uint8>& rawData); };
NetAPI.cpp:
#include "NetAPI.h" #include "NetAPI.h" #include "Http.h" FHttpModule* UNetAPI::GetHttpModule() { static FHttpModule* httpModule = NULL; if (httpModule == NULL ) { httpModule = &FHttpModule::Get(); httpModule->SetHttpTimeout( 60 ); httpModule->SetMaxReadBufferSize( 1024 * 1024 * 50 ); httpModule->SetHttpDelayTime( 0.001 ); //temp_module->AddDefaultHeader(TEXT("Cache-Control"), TEXT("no-cache")); } return httpModule; } FHttpManager& UNetAPI::GetHttpMgr() { return UNetAPI::GetHttpModule()->GetHttpManager(); } TSharedRef<IHttpRequest> UNetAPI::createRequst(FString _url, FString _method, FString _content, FString _contentType) { TSharedRef<IHttpRequest> ret_request = UNetAPI::GetHttpModule()->CreateRequest(); ret_request->SetHeader(TEXT("Content-Type"), _contentType); ret_request->SetURL(_url); ret_request->SetVerb(_method); if ( _method == TEXT("POST") ) { ret_request->SetContentAsString(_content); } return ret_request; } TSharedRef<IHttpRequest> UNetAPI::createUploadImageRequest(FString _url, TArray<uint8>& rawData) { TSharedRef<IHttpRequest> ret_request = UNetAPI::GetHttpModule()->CreateRequest(); ret_request->SetURL(_url); ret_request->SetHeader(TEXT("Content-Type"), TEXT("text/html;charset=UTF-8")); ret_request->SetVerb(TEXT("POST")); ret_request->SetContent(rawData); return ret_request; }
下载图片帮助类:
DownloadImageHelper.h:
#pragma once #include "CoreMinimal.h" #include "IImageWrapper.h" #include "Interfaces/IHttpRequest.h" #include "Engine/Texture2D.h" /** * */ class LQCOREPLUGIN_API FDownloadImageHelper { public: FDownloadImageHelper(); ~FDownloadImageHelper(); void Start(const FString &Url); void Start(const FString &Url, UObject *target,void(UObject::* bindfunc)(bool, UTexture2D *)); public: DECLARE_EVENT_TwoParams(FString, FOnDownloadCompleted, bool, UTexture2D*); FOnDownloadCompleted& OnDownloadCompleted() { return Event_OnDownloadCompleted; } protected: #pragma region Http Event Handle void Http_HandleCompleted(FHttpRequestPtr Req, FHttpResponsePtr Res, bool bConnectedSuccessfully); #pragma endregion protected: FOnDownloadCompleted Event_OnDownloadCompleted; };
DownloadImageHelper.cpp:
#include "DownloadImageHelper.h" #include "CoreBPLibrary.h" #include "API/NetAPI.h" #include "Modules/ModuleManager.h" #include "IImageWrapperModule.h" FDownloadImageHelper::FDownloadImageHelper() { } FDownloadImageHelper::~FDownloadImageHelper() { } void FDownloadImageHelper::Start(const FString &Url) { FString encodeUrl = UCoreBPLibrary::UrlEncode(Url); //中文转码 auto req = UNetAPI::createRequst(encodeUrl, TEXT("GET"), TEXT("application/octet-stream;image/png;image/jpeg;")); req->OnProcessRequestComplete().BindRaw(this, &FDownloadImageHelper::Http_HandleCompleted); if (!req->ProcessRequest()) { UE_LOG(LogHttp, Error, TEXT("----------------------- request Process Request invaild")); } } void FDownloadImageHelper::Start(const FString & Url, UObject *target, void(UObject::* bindfunc)(bool, UTexture2D *)) { this->OnDownloadCompleted().AddUObject(target, bindfunc); this->Start(Url); } void FDownloadImageHelper::Http_HandleCompleted(FHttpRequestPtr Req, FHttpResponsePtr Res, bool bConnectedSuccessfully) { FString Url = Req->GetURL(); if (!bConnectedSuccessfully || !Res.IsValid() || Res->GetResponseCode() != 200) { UE_LOG( LogHttp, Error, TEXT("-------- : req occur error from Url {%s} : error info: {%s}."), *Url, *(Res->GetContentAsString()) ); this->OnDownloadCompleted().Broadcast(false, nullptr); return; } #pragma region 从Url判断图片类型/NOte:也可以从Content-Type中判断 EImageFormat ImageFormat = EImageFormat::JPEG; { TArray<FString> arr_regex; bool isJPG = UCoreBPLibrary::RegexMatch(Url, TEXT(".\\.jpg$|.\\.jpeg$|.\\.jpe$"), arr_regex); arr_regex.Empty(); bool isPNG = UCoreBPLibrary::RegexMatch(Url, TEXT(".\\.png$"), arr_regex); arr_regex.Empty(); bool isHDR = UCoreBPLibrary::RegexMatch(Url, TEXT(".\\.exr$|.\\.hdr$"), arr_regex); arr_regex.Empty(); if (isPNG) { ImageFormat = EImageFormat::PNG; } if (isJPG) { ImageFormat = EImageFormat::JPEG; } if (isHDR) { ImageFormat = EImageFormat::EXR; } } #pragma endregion TArray<uint8> binarayData = Res->GetContent(); IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper")); TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(ImageFormat); if (!ImageWrapper.IsValid() || !ImageWrapper->SetCompressed(binarayData.GetData(), binarayData.Num())) { UE_LOG(LogHttp, Error, TEXT("ImageWrapper can't Set Compressed or ImageWrapper is InValid")); this->OnDownloadCompleted().Broadcast(false, nullptr); return; } const TArray<uint8>* rawData = nullptr; UTexture2D* LoadedT2D = nullptr; void* TextureData = nullptr; if (!ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, rawData)) { UE_LOG(LogTemp, Warning, TEXT("can't get Raw temp_unCompressedRGBA")); this->OnDownloadCompleted().Broadcast(false, nullptr); return; } #pragma region 创建T2D int32 w = ImageWrapper->GetWidth(); int32 h = ImageWrapper->GetHeight(); LoadedT2D = UTexture2D::CreateTransient(w, h, PF_B8G8R8A8); #pragma endregion #pragma region 内存拷贝 TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE); FMemory::Memcpy(TextureData, rawData->GetData(), rawData->Num()); #pragma endregion #pragma region 更新T2D LoadedT2D->PlatformData->Mips[0].BulkData.Unlock(); LoadedT2D->UpdateResource(); #pragma endregion this->OnDownloadCompleted().Broadcast( true, LoadedT2D); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理