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);
}