【UE4】DownloadImage添加Token验证方法

 前言:项目用到URL图片,但是该URL需要使用Token进行验证,UE自带的节点DownloadImage还是有局限性,只能访问无验证的页面,so我们来重写---带token验证版的DownloadImage方法(此方法与官方RHI不同)。

(商店版引擎的实用方案,源码版的去改源码实现更快)


1.准备工作:

  • UE4C++项目中创建新的C++异步任务类继承自:BlueprintAsyncActionBase

2.添加模块并编写代码:

  • 项目Build.cs中添加模块:HTTP,ImageWrapper,RHI(未使用可不添加)

.h头文件中:

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Interfaces/IHttpRequest.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Modules/ModuleManager.h"
#include "Engine/Texture2D.h"
#include "Engine/Texture2DDynamic.h"
#include "IImageWrapper.h"
#include "IImageWrapperModule.h"
#include "Runtime\Online\HTTP\Public\Interfaces\IHttpResponse.h"
#include "Runtime\Online\HTTP\Public\HttpModule.h"
#include "Runtime\Engine\Classes\Kismet\KismetStringLibrary.h"
#include <RHIResources.h>
#include <TextureResource.h>
#include "BAATask.generated.h"

class UTexture2DDynamic;//useless

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDownloadImageDelegateMY, UTexture2D*, Texture);
/**
 * 
 */
UCLASS()
class CQSHUILINEW_API UBAATask : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	UBAATask(const FObjectInitializer& ObjectInitializer);

	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
		static UBAATask* DownloadImage(FString URL,FString Token);

public:
	UPROPERTY(BlueprintAssignable)
		FDownloadImageDelegateMY Success;
	UPROPERTY(BlueprintAssignable)
		FDownloadImageDelegateMY Fail;
public:

	FString IMGurl="";

	void Start(FString URL,FString Token);

	UTexture2D* GetTexture(TSharedPtr<IImageWrapper> ImageWrapper, FHttpResponsePtr HttpResponse);
	
	void HandleImageRequest(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded);
};
  • .cpp中:

    #include "BAATask.h"
    #include <cctype>
    #include <iomanip>
    #include <sstream>
    #include <string>
    
    using namespace std;
    
    UBAATask::UBAATask(const FObjectInitializer& ObjectInitializer)
    	: Super(ObjectInitializer)
    {
    	if (HasAnyFlags(RF_ClassDefaultObject) == false)
    	{
    		AddToRoot();
    	}
    }
    
    UBAATask* UBAATask::DownloadImage(FString URL,FString Token)
    {
    	UBAATask* DownloadTask = NewObject<UBAATask>();
    	DownloadTask->Start(URL,Token);
    	return DownloadTask;
    }
    
    void UBAATask::Start(FString URL,FString Token)
    {
    #if !UE_SERVER
    	TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HttpRequest = FHttpModule::Get().CreateRequest();
    
    	HttpRequest->OnProcessRequestComplete().BindUObject(this, &UBAATask::HandleImageRequest);
    	FString Lurl="";
    	FString Rurl="";
    	FString Unuse="";//useless value
    	UKismetStringLibrary::Split(URL, "/", Lurl, Rurl, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
    	UKismetStringLibrary::Split(Rurl, "/", Unuse, Rurl, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
    
    	//URL encode For Chinese(UTF-8)
    	ostringstream escaped;
    	escaped.fill('0');
    	escaped << hex;
    	string vaule= TCHAR_TO_UTF8(*Rurl);
    	for (string::const_iterator i = vaule.begin(), n = vaule.end(); i != n; ++i) {
    		string::value_type c = (*i);
    		if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
    			escaped << c;
    			continue;
    		}
    		escaped << uppercase;
    		escaped << '%' << setw(2) << int((unsigned char)c);
    		escaped << nouppercase;
    	}
    
    	HttpRequest->SetURL(Lurl + "/" + FString(escaped.str().c_str()));//urlencode2fstring
    	IMGurl =URL;//For bool if jpg or png
    	HttpRequest->SetVerb(TEXT("GET"));
    	HttpRequest->SetHeader(TEXT("X-Access-Token"), Token);//in Token
    	HttpRequest->ProcessRequest();
    #else
    	RemoveFromRoot();
    #endif
    }
    
    void UBAATask::HandleImageRequest(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded)
    {
    	UTexture2D* Texture = nullptr;//create Texture2D
    	
    	IImageWrapperModule& module = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
    	if(UKismetStringLibrary::Contains(*IMGurl,TEXT(".jpg"),ESearchCase::IgnoreCase,ESearchDir::FromStart)|| UKismetStringLibrary::Contains(*IMGurl, TEXT(".jpeg"), ESearchCase::IgnoreCase, ESearchDir::FromStart))
    	{
    		TSharedPtr<IImageWrapper> ImageWrapper = module.CreateImageWrapper(EImageFormat::JPEG);
    		Texture = GetTexture(ImageWrapper,HttpResponse);
    		Success.Broadcast(Texture);//success return texture2d
    		return;
    	}else if(UKismetStringLibrary::Contains(*IMGurl, TEXT(".png"), ESearchCase::IgnoreCase, ESearchDir::FromStart))
    	{
    		TSharedPtr<IImageWrapper> ImageWrapper = module.CreateImageWrapper(EImageFormat::PNG);
    		Texture = GetTexture(ImageWrapper, HttpResponse);
    		Success.Broadcast(Texture);//success return texture2d
    		return;
    	}
    	Fail.Broadcast(nullptr);//fail nullptr
    }
    
    UTexture2D* UBAATask::GetTexture(TSharedPtr<IImageWrapper> ImageWrapper, FHttpResponsePtr HttpResponse)
    {
    	if (ImageWrapper->SetCompressed(HttpResponse->GetContent().GetData(), HttpResponse->GetContentLength()))
    	{
    		TArray<uint8> UncompressedRGBA;
    		if (ImageWrapper->GetRaw(ERGBFormat::RGBA, 8, UncompressedRGBA))
    		{
    			UTexture2D* Texture = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_R8G8B8A8);
    			if (Texture != nullptr)
    			{
    				//int OutWidth = ImageWrapper->GetWidth();//w&h
    				//int OutHeight = ImageWrapper->GetHeight();
    				void* TextureData = Texture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
    				FMemory::Memcpy(TextureData, UncompressedRGBA.GetData(), UncompressedRGBA.Num());
    				Texture->PlatformData->Mips[0].BulkData.Unlock();
    				Texture->UpdateResource();
    				return Texture;
    			}
    		}
    	}
    	return nullptr;
    }

    3.编译后蓝图传入地址与Token处理成功设置笔刷:

     


     后言:考虑到验证访问地址图片时URL中带有中文时需要urlencode进行转码后转回Fstring才能正常访问地址,把图片处理单独写成一个函数便于处理不同格式的图片;

  • 希望这篇文章能帮到你!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值