공부 기록

[UE4] Http Request 를 이용한 서버 파일 업로드 본문

Unreal/C++

[UE4] Http Request 를 이용한 서버 파일 업로드

혜멘 2022. 4. 15. 16:24

ue4 file upload to server using http post request

언리얼에서 지원하는 Http request 를 통해 서버에 파일을 업로드 하는 방법이다.

POST 방식을 사용하며, url에 정보를 포함하는 GET과 달리 POST는 body에 정보를 담아 보내므로 바디 부분을 직접 작성해줘야 한다.

 

이때 파일을 담으려면 multipart/form-data 형식을 사용해야 하며, multipart는 정보를 여러개 보낼 때 사용하므로 서버가 각각의 정보를 어디서부터 어디까지 읽을지를 지정해주기 위해 boundary 플래그를 사용해야한다.

 

boundary는 다른 정보와 겹치지 않는 랜덤화된 문자열을 사용하고, body를 읽기 전에 서버가 알 수 있도록 헤더에 포함해준다.

 

헤더에 알맞은 정보를 모두 지정해주고나면 body에 들어갈 파일의 정보를 지정한다.

먼저 boundary를 표시하고 파일 정보를 쓴다. 추가 파일이 있다면 이전 파일과의 경계 표시를 위해 boundary 를 쓰고 나서 그 뒤에 파일 정보를 써준다. 모든 정보가 끝나면 boundary 를 한번 더 표시하여 더 이상 읽을 것이 없다고 서버에게 알려준다. 이 때 주의할 점은 boundary-- 라고 표시해줘야 종료 표시로 알아듣는다.

 

아래 코드에 주석을 친절하게 달아뒀으니 보고 이해하도록 하자!

#include "Runtime/Online/HTTP/Public/Http.h"
#include "Interfaces/IHttpRequest.h"

void UMyHttpWidget::UploadFile(FString URL, FString FilePath)
{
	// 업로드할 파일 데이터
    TArray<uint8> UpFileRawData;
    FFileHelper::LoadFileToArray(UpFileRawData, *FilePath);
	
    // htttp 리퀘스트 생성
    TSharedRef<IHttpRequest, ESPMode::ThreadSafe> httpRequest = FHttpModule::Get().CreateRequest();
	
    // 리퀘스트를 받을 php 파일의 주소
    httpRequest->SetURL(URL);
	
    // post 통신
    httpRequest->SetVerb(TEXT("POST"));
    
    // 파일이 시작하는 지점을 알려주는 boundary 플래그, 헤더에 포함하여 서버가 미리 알 수 있도록 함
    const FString boundary(TEXT("------------------------axcvv68d9we0asdg")); 
    httpRequest->SetHeader(TEXT("Content-Type"), TEXT("multipart/form-data; boundary=") + boundary);
    httpRequest->SetHeader(TEXT("Accept"), TEXT("*/*"));
    httpRequest->SetHeader(TEXT("Expect"), TEXT("100-continue"));
    
	// boundary 플래그를 사용해 여기서부터 파일 정보임을 알려줌
	const FString prefixBoundary(TEXT("--") + boundary + TEXT("\r\n"));
	const FString fileHeader(TEXT("Content-Disposition: form-data; name=\"fileToUpload\"; filename="지정하고싶은파일이름.txt"; Content - Type: application / octet - stream\r\n\r\n"));
	const FString suffixBoundary(TEXT("\r\n--") + boundary + TEXT("--\r\n"));
	// 파일 정보가 끝나는 부분에도 boundary 플래그를 사용해줌, 끝에 -- 를 붙임

	TArray<uint8> CombinedContent;
	CombinedContent.Append(FStringToUint8(prefixBoundary + fileHeader));	// 바운더리 표시 후 파일 정보 입력
	CombinedContent.Append(UpFileRawData);									// 파일 업로드
	CombinedContent.Append(FStringToUint8(suffixBoundary));					// 읽기 종료 표시
	
    // content body에 파일 정보 추가
    httpRequest->SetContent(CombinedContent);
    
     // 리퀘스트의 결과를 받아오는 함수 바인딩
    httpRequest->OnProcessRequestComplete().BindUObject(this, &UW_EditMap::OnResponseReceived);
    httpRequest->ProcessRequest();

}

TArray<uint8> UMyHttpWidget::FStringToUint8(const FString& InString)
{
	TArray<uint8> OutBytes;

	// Handle empty strings
	if (InString.Len() > 0)
	{
		FTCHARToUTF8 Converted(*InString); // Convert to UTF8
		OutBytes.Append(reinterpret_cast<const uint8*>(Converted.Get()), Converted.Length());
	}

	return OutBytes;
}

// 리퀘스트 결과를 받아와 출력함
void UW_EditMap::OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
	FString _Response = Response->GetContentAsString();
	if (bWasSuccessful) UE_LOG(LogTemp, Warning, TEXT("Success   %s"), *_Response);
}
Comments